The 6th Liaoning Provincial Collegiate Programming Contest - External 复盘

AC:7

D:

#include<bits/stdc++.h>

#define int long long

#define inf 0x3f3f3f3f3f3f3f

#define GG ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

#define cnot cout<<"NO"<<"\n"

#define cyes cout<<"YES"<<"\n"

#define cans cout<<ans<<"\n"

#define pb push_back

#define x0 first

#define y0 second

#define lc p<<1

#define rc p<<1|1

#define mem(a,b) memset(a,b,sizeof(a))

#define sp(x) fixed<<setprecision(x)

#define all(v) v.begin(),v.end()

#define fr(i,st,ed) for(int i=st;i<=ed;i++)

#define ffr(i,st,ed,dt) for(int i=st;i<=ed;i+=dt)

using namespace std;

typedef pair<int,string>Pis;

typedef pair<int,int>Pii;

typedef pair<string,string>Pss;

const int N=2e4+10,mod=1e9+7,M=1e6+10;

int lowbit(int x){

return x&(-x);}

void solve(){

int n;

cin>>n;

vector<vector<int>>a(n+1,vector<int>(4));

fr(i,1,n){

fr(j,1,3){

cin>>aij;

}

}

/*

int num1=0;

int num2=0;

int num3=0;

*/

bitset<105>num1,num2,num3,Ans;

fr(i,1,n){

fr(j,1,3){

if(j==1&&aij==1)num1.set((i-1));

if(j==2&&aij==1)num2.set((i-1));

if(j==3&&aij==1)num3.set((i-1));

Ans.set((i-1));

}

}

/*

cout<<(num1|num2)<<endl<<(num2|num3)<<endl<<(num1|num3)<<endl;

cout<<(1<<n)-1<<endl;

*/

if(num1==Ans||num2==Ans||num3==Ans)cout<<1<<"\n";

else if(((num1|num2)==Ans)||((num1|num3)==Ans)||((num2|num3)==Ans))cout<<2<<"\n";

else cout<<3<<"\n";

}

signed main(){

GG;

int _t=1;

//cin>>_t;

while(_t--){

solve();

}

}

E:

因为最大数字只可能是1-9,很容易想到尝试枚举出现的最大数字;

接下来考虑对于每一个最大数字,如何找到每一段区间;

我们1-n扫描整个数组,对于每个i,我们希望统计以i为右端点的数组个数,所以我们需要确定此时左端点的合法区间

对于左端点存在的区间,显然,如果上一个数>D(此时枚举的最大数字),那么左区间应该被更新为i,同时右区间应该被设为不存在,如果上一个数==D,那么右区间应该被更新为i-1,直到下一个等于D的数出现;

解释一下这么寻找的理由:对于每一个右端点,我们希望它向前寻找左端点构成的区间里面含有一个D,同时不含>D的数,那我至少需要找到上一个D存在的位置,同时这段区间不能有>D的数,至多找到上一个>D出现的位置后一位;

画个图帮助理解:

现在考虑如何在这段区间找左端点使得区间和整除于D;

我们知道,在mod m意义下的前缀和相同等价这两个前缀和直接的区间和%m==0;

所以,将mod m意义下每个数出现的位置存一下;

比如 pos1 里面存的就是 mod m意义下为1的数的位置;

而现在我们知道了L,R;

等价于在一个数组里面求两个数之间有多少数

这是一个经典二分求点距离的问题;

至此这道题的思路就完成了,具体实现看code:

#include<bits/stdc++.h>

#define int long long

#define inf 0x3f3f3f3f3f3f3f

#define GG ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

#define cnot cout<<"NO"<<"\n"

#define cyes cout<<"YES"<<"\n"

#define cans cout<<ans<<"\n"

#define pb push_back

#define x0 first

#define y0 second

#define lc p<<1

#define rc p<<1|1

#define mem(a,b) memset(a,b,sizeof(a))

#define sp(x) fixed<<setprecision(x)

#define all(v) v.begin(),v.end()

#define fr(i,st,ed) for(int i=st;i<=ed;i++)

#define ffr(i,st,ed,dt) for(int i=st;i<=ed;i+=dt)

using namespace std;

typedef pair<int,string>Pis;

typedef pair<int,int>Pii;

typedef pair<string,string>Pss;

const int N=2e4+10,mod=1e9+7,M=1e6+10;

int lowbit(int x){

return x&(-x);}

int getmax(int x){

int res=0;

while(x>0){

int num=x%10;

res=max(res,num);

x/=10;

}

return res;

}

vector<int>Cnt(10);

void solve(){

int n;

cin>>n;

vector<int>a(n+1),Max(n+1);

fr(i,0,n-1){

cin>>ai;

Maxi=getmax(ai);

}

int ans=0;

fr(D,1,9){

vector<vector<int>>pos(D);

pos0.pb(0LL);

int lst1=0;

int lst2=-1;

int cur=0;

fr(i,1,n){

cur=(cur+(ai-1%D))%D;

if(Maxi-1>D){

lst1=i;

lst2=-1;

}

else if(Maxi-1==D){

lst2=i;

}

if(lst2!=-1){

int L=lst1;

int R=lst2-1;

//auto v=poscur;

const auto& v=poscur;

auto it1=lower_bound(all(v),L);

auto it2=upper_bound(all(v),R);

ans+=(int)distance(it1,it2);

}

poscur.pb(i);

}

}

cans;

}

signed main(){

GG;

int _t=1;

cin>>_t;

while(_t--){

solve();

}

}

M

我们可以把比赛分成两种,a>=b a<b;

对于第一种比赛,我们把a从小到大排,不难发现,只要顺次完成他们,他们一定都可以被进行,因为完成比赛的提升比要求小,而下一场的要求总是高于这一场的要求;

所以我们的目标应该是:在确保所有第一种比赛可以完成的情况下,尽可能多的完成第二种比赛;

我们考虑第二种比赛对第一种比赛的影响,很显然是能力提升到b,那么我们只要把需求值小于b的所有比赛打完,这次比赛的结果就不会对第一组产生影响,这时我们只要判断此时的能力能否参加这场比赛,能参加就参加,不能则跳过看下一个;

所以对第二种比赛排序的第一关键字是b;

这个贪心的合理性在于,第一种比赛能否全部打完是稳定可控的,为了顺利打完第一组比赛,对于每个第二组中的比赛来说至多是放弃一场,而打第二组比赛的影响是不可控的,因此减少的比赛场数只可能更多;

实现见code:

#include<bits/stdc++.h>

#define int long long

#define inf 0x3f3f3f3f3f3f3f

#define GG ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

#define cnot cout<<"NO"<<"\n"

#define cyes cout<<"YES"<<"\n"

#define cans cout<<ans<<"\n"

#define pb push_back

#define x0 first

#define y0 second

#define lc p<<1

#define rc p<<1|1

#define mem(a,b) memset(a,b,sizeof(a))

#define sp(x) fixed<<setprecision(x)

#define all(v) v.begin(),v.end()

#define fr(i,st,ed) for(int i=st;i<=ed;i++)

#define ffr(i,st,ed,dt) for(int i=st;i<=ed;i+=dt)

using namespace std;

typedef pair<int,string>Pis;

typedef pair<int,int>Pii;

typedef pair<string,string>Pss;

const int N=2e4+10,mod=1e9+7,M=1e6+10;

int lowbit(int x){

return x&(-x);}

bool cmp1(Pii a,Pii b){//a

return a.x0==b.x0?a.y0>b.y0:a.x0<b.x0;

}

bool cmp2(Pii a,Pii b){//b

return a.y0==b.y0?a.x0<b.x0:a.y0<b.y0;

}

void solve(){

int n;

cin>>n;

vector<Pii>ta,tb;

//ta:a>=b

//tb:a<b

int x,y;

fr(i,1,n){

cin>>x>>y;

if(x>=y){

ta.pb({x,y});

}

else{

tb.pb({x,y});

}

}

int res=0;

sort(all(ta),cmp1);

sort(all(tb),cmp2);

int sza=ta.size();

int szb=tb.size();

int idxa=0;

int idxb=0;

int cur=0;

while(idxb<szb){

while(idxa<sza&&idxb<szb&&taidxa.x0<tbidxb.y0){

cur=max(cur,taidxa.y0);

idxa++;

}

if(cur<=tbidxb.x0){

res++;

cur=max(cur,tbidxb.y0);

}

idxb++;

}

int ans=res+sza;

cans;

}

signed main(){

GG;

int _t=1;

//cin>>_t;

while(_t--){

solve();

}

}

相关推荐
Dillon Dong2 小时前
【风电控制】TI TMS320F28379D 双CPU架构解析与任务分布设计
嵌入式硬件·算法·变流器·风电控制
小羊在睡觉7 小时前
力扣84. 柱状图中最大的矩形
后端·算法·leetcode·golang·go
3DVisionary8 小时前
蓝光三维扫描:医疗制造的精度焦虑怎么解
人工智能·算法·制造·蓝光三维扫描·医疗制造·三维检测·义齿检测
好评笔记8 小时前
机器学习面试八股——常用损失函数
人工智能·深度学习·算法·机器学习·校招
weixin_468466858 小时前
全局与局部注意力机制新手实战指南
人工智能·python·深度学习·算法·自然语言处理·transformer·注意力机制
_日拱一卒8 小时前
LeetCode:994腐烂的橘子
java·数据结构·算法·leetcode·深度优先
珂朵莉MM9 小时前
第七届全球校园人工智能算法精英大赛-算法巅峰赛产业命题赛第3赛季优化题--束搜索
人工智能·算法
Omics Pro9 小时前
首个!外源天然产物综合性代谢图谱
数据库·人工智能·算法·机器学习·r语言
voidmort10 小时前
3. 微调(Fine-tuning)与强化学习(RL)的核心思想
python·深度学习·算法
人道领域10 小时前
【LeetCode刷题日记】669.修剪二叉搜索树
开发语言·python·算法