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>>a[i][j];
}
}
/*
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&&a[i][j]==1)num1.set((i-1));
if(j==2&&a[i][j]==1)num2.set((i-1));
if(j==3&&a[i][j]==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意义下每个数出现的位置存一下;
比如 pos[1] 里面存的就是 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>>a[i];
Max[i]=getmax(a[i]);
}
int ans=0;
fr(D,1,9){
vector<vector<int>>pos(D);
pos[0].pb(0LL);
int lst1=0;
int lst2=-1;
int cur=0;
fr(i,1,n){
cur=(cur+(a[i-1]%D))%D;
if(Max[i-1]>D){
lst1=i;
lst2=-1;
}
else if(Max[i-1]==D){
lst2=i;
}
if(lst2!=-1){
int L=lst1;
int R=lst2-1;
//auto v=pos[cur];
const auto& v=pos[cur];
auto it1=lower_bound(all(v),L);
auto it2=upper_bound(all(v),R);
ans+=(int)distance(it1,it2);
}
pos[cur].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&&ta[idxa].x0<tb[idxb].y0){
cur=max(cur,ta[idxa].y0);
idxa++;
}
if(cur<=tb[idxb].x0){
res++;
cur=max(cur,tb[idxb].y0);
}
idxb++;
}
int ans=res+sza;
cans;
}
signed main(){
GG;
int _t=1;
//cin>>_t;
while(_t--){
solve();
}
}