Codeforces Round #452 (Div. 2)
第一场补题AK场(纪念一下下
A:给你N个数 求最多怎么分类使和为3的个数最多
水题直接分类讨论即可
#include <bits/stdc++.h> #define N 200005 using namespace std; int main(){ int n;cin>>n; int cnt1=0;int cnt2=0; int t; for(int i=1;i<=n;i++) { cin>>t; if(t==1) cnt1++; else cnt2++; } int ans=0; if(cnt2>cnt1){ cout<<cnt1<<endl; return 0; } else{ ans+=(cnt2); cnt1-=cnt2; ans+=(cnt1/3); cout<<ans<<endl; return 0; } return 0; }
B:给你N个数字 问这些数字可不可能是一年中连续出现的月份(可能是闰年)
(from sb红) 由n<24可知,输入的的月份最多跨三个年份,由此可以构造出一个连续年中的月份天数表,只要将输入序列与表相比较,匹配则输出YES,反之NO。
关于表的构造:第一种是比赛的时候写的那种,分1无闰年,2第一年闰,3第二年闰,4第三年闰四种情况。第二种是构造一个长度为六年的表(如:闰平平平闰平)即可包括第一种的所有情况。
关于匹配:都是常数级别直接暴力匹配即可,闲的无聊可以用KMP优化匹配
关于匹配:都是常数级别直接暴力匹配即可,闲的无聊可以用KMP优化匹配
#include<bits/stdc++.h> using namespace std; int a[30]; int b[10][36]={{31,28,31,30,31,30,31,31,30,31,30,31, 31,28,31,30,31,30,31,31,30,31,30,31, 31,28,31,30,31,30,31,31,30,31,30,31,} ,{31,29,31,30,31,30,31,31,30,31,30,31, 31,28,31,30,31,30,31,31,30,31,30,31, 31,28,31,30,31,30,31,31,30,31,30,31,} ,{31,28,31,30,31,30,31,31,30,31,30,31, 31,29,31,30,31,30,31,31,30,31,30,31, 31,28,31,30,31,30,31,31,30,31,30,31,} ,{31,28,31,30,31,30,31,31,30,31,30,31, 31,28,31,30,31,30,31,31,30,31,30,31, 31,29,31,30,31,30,31,31,30,31,30,31,}}; int main() { int n,k; bool ans=false; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",&a[i]); for(int i=0;i<4;i++) for(int j=0;j<36;j++) { if(a[0]==b[i][j]) { for(k=1;k<n;k++) if(a[k]!=b[i][k+j]) break; if(k==n) ans=true; } } if(ans) printf("YES\n"); else printf("NO\n"); return 0; }
C:给一个数字n 问如何对1-n这个数字进行分类 使两类和的绝对值之差最小 输出这个最小值 并输出任意一类的数字
题解:贪心题 从后往前 判断这个数加入哪一堆 只需要模拟这个过程最符合条件即可
#include <bits/stdc++.h> using namespace std; int ab(int a,int b){ int t=a-b; if(t>0) return t; else return -1*t; } int main(){ int n;cin>>n; int cnt1=0;int cnt2=0; vector<int>v1;vector<int>v2; for(int i=n;i>=1;i--){ if(cnt1==cnt2){ v1.push_back(i);cnt1+=i; } else if(ab(cnt1+i,cnt2)<ab(cnt2+i,cnt1)){ v1.push_back(i);cnt1+=i; } else{ v2.push_back(i);cnt2+=i; } } cout<<ab(cnt1,cnt2)<<endl; cout<<v1.size(); for(int i=0;i<v1.size();i++){ cout<<" "<<v1[i]; } cout<<endl; return 0; }
D:form(jlz)
思路就是先根据n+(n-1)找出满足条件的最大末尾连续9的个数,比如50就是99,最大就是两个9,只有99满足,而1到50中相加能等于99就只有50+49,即min(n-99/2,99/2)
可以看出当n+n-1={9,99,999,9999,99999,999999,9999999,99999999,999999999}时为1;
当n+n-1<9时为n*(n-1)/2;
其余情况则保持9的个数为最大,将首位从本来的数枚举到0,然后每次对枚举的那个数(假设为x&&x<n+n-1
)算出min(n-x/2,x/2),比如对于12来说,12+11=23,枚举首位从2到0
1.x=29,29>23,继续枚举,x=19,19<23,则ans+=min(12-19/2,19/2),继续枚举,x=9<23,则ans+=min(12-9/2,9/2);最后ans=3+4=7
可以看出当n+n-1={9,99,999,9999,99999,999999,9999999,99999999,999999999}时为1;
当n+n-1<9时为n*(n-1)/2;
其余情况则保持9的个数为最大,将首位从本来的数枚举到0,然后每次对枚举的那个数(假设为x&&x<n+n-1
)算出min(n-x/2,x/2),比如对于12来说,12+11=23,枚举首位从2到0
1.x=29,29>23,继续枚举,x=19,19<23,则ans+=min(12-19/2,19/2),继续枚举,x=9<23,则ans+=min(12-9/2,9/2);最后ans=3+4=7
#include<bits/stdc++.h> using namespace std; #define ll long long #define N 1000010 ll n,s,weishu,ans,shouwei,tt; ll qaq[]={9,99,999,9999,99999,999999,9999999,99999999,999999999}; void cal(){ for(int i=0;i<9;i++){ if(s==qaq[i]){ cout<<1<<endl; exit(0); } } tt=upper_bound(qaq,qaq+9,s)-qaq; if(tt==0){ cout<<n*(n-1)/2<<endl; exit(0); } else tt=qaq[tt-1]; ll aa=s; while(aa){ weishu++; if(aa<10) shouwei=aa; aa/=10; } } int main(){ while(cin>>n){ weishu=0,shouwei=0,tt=0,ans=0; s=2*n-1; cal(); for(int i=shouwei;i>=0;i--){ ll qq=i; for(int j=weishu;j>1;j--){ qq*=10; } qq+=tt; if(qq>s){ continue; } ans+=min(n-qq/2,qq/2); } cout<<ans<<endl; } return 0; }
E:题意:给你n个数 每次去掉连续次数最多的一串数(如果有多个 应优先删除靠左边的)
直接线段树合并维护最长连续区间 对于已经删除的区间不进行合并即可 细节挺多,对拍好久找出WA点
#include <iostream> #include <algorithm> #include <cstdio> #define ll long long #define N 200005 using namespace std; typedef struct node{ int l,r,l2,r2; ll l1;ll r1;int len1;int len2;int len;int id;int id1; int flag; }node; node d[N<<2]; ll a[N]; void push(int root){ if(d[root].flag==1){ d[root<<1].l1=0;d[root<<1].r1=0;d[root<<1].len1=0;d[root<<1].len2=0;d[root<<1].len=0;d[root<<1].id=d[root<<1].l;d[root<<1].id1=d[root<<1].r; d[root<<1|1].l1=0;d[root<<1|1].r1=0;d[root<<1|1].len1=0;d[root<<1|1].len2=0;d[root<<1|1].len=0;d[root<<1|1].id=d[root<<1|1].l;d[root<<1|1].id1=d[root<<1|1].r; d[root<<1].flag=1;d[root<<1|1].flag=1;d[root].flag=0; } } void up(int root){ if(d[root<<1].l1==0&&d[root<<1|1].l1==0){ d[root].l1=0;d[root].r1=0;d[root].len=0;d[root].len1=0;d[root].len2=0;d[root].id=d[root<<1].l; d[root].id1=d[root<<1|1].r; return ; } else if(d[root<<1].l1==0){ d[root]=d[root<<1|1]; return ; } else if(d[root<<1|1].r1==0){ d[root]=d[root<<1]; return ; } d[root].l1=d[root<<1].l1;d[root].r1=d[root<<1|1].r1; d[root].l=d[root<<1].l;d[root].r=d[root<<1|1].r; d[root].l2=d[root<<1].l2;d[root].r2=d[root<<1|1].r2; if(d[root<<1].len>=d[root<<1|1].len){ d[root].len=d[root<<1].len;d[root].id=d[root<<1].id; d[root].id1=d[root<<1].id1; } else { d[root].len=d[root<<1|1].len;d[root].id=d[root<<1|1].id; d[root].id1=d[root<<1|1].id1; } //cout<<d[root<<1].r2<<"====="<<d[root<<1|1].l2<<endl; if(d[root<<1].r1==d[root<<1|1].l1){ if(d[root<<1].len2+d[root<<1|1].len1>=d[root].len){ if(d[root<<1].len2+d[root<<1|1].len1==d[root].len){ d[root].id=min(d[root<<1].r2,d[root].id); d[root].id1=min(d[root<<1|1].l2,d[root].id1); } else{ d[root].id=d[root<<1].r2; d[root].id1=d[root<<1|1].l2;} d[root].len=d[root<<1].len2+d[root<<1|1].len1; } if(d[root<<1].l2==d[root<<1].r) { d[root].l2=d[root<<1|1].l2; d[root].len1=d[root<<1].len1+d[root<<1|1].len1;} else d[root].len1=d[root<<1].len1; if(d[root<<1|1].r2==d[root<<1|1].l) { d[root].r2=d[root<<1].r2; d[root].len2=d[root<<1|1].len2+d[root<<1].len2; } else d[root].len2=d[root<<1|1].len2; } else{ d[root].len1=d[root<<1].len1;d[root].len2=d[root<<1|1].len2; } // cout<<d[root].l<<"=================="<<d[root].r<<" "<<d[root].r2<<endl; } void built(int root,int l,int r){ if(l==r){ d[root].l=l;d[root].r=r;d[root].l2=l;d[root].r2=r; d[root].l1=a[l];d[root].r1=a[l];d[root].len1=1;d[root].len2=1;d[root].len=1;d[root].id=l; d[root].flag=0;d[root].id1=l; return ; } int mid=(l+r)>>1; built(root<<1,l,mid); built(root<<1|1,mid+1,r); d[root].l=d[root<<1].l;d[root].r=d[root<<1|1].r; d[root].flag=0; up(root); } void update(int root,int l,int r,int t,int l1,int r1){ if(l<=l1&&r1<=r){ d[root].flag=1; d[root].l1=0;d[root].r1=0;d[root].len1=0;d[root].len2=0;d[root].len=0; d[root].id=d[root].l;d[root].id1=d[root].r; return ; } push(root); int mid=(l1+r1)>>1; if(l<=mid) update(root<<1,l,r,t,l1,mid); if(r>mid) update(root<<1|1,l,r,t,mid+1,r1); up(root); // cout<<d[root].l<<" "<<d[root].r<<" "<<d[root].id<<" "<<d[root].id1<<endl; // cout<<d[root].l<<"======"<<d[root].r<<" "<<d[root<<1|1].len1<<" "<<d[root<<1].r2<<" "<<d[root<<1|1].l2<<endl; } int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); built(1,1,n); int ans=0; while(d[1].len!=0){ ans++; // cout<<d[1].id<<" "<<d[1].id1<<" "<<d[1].len<<endl; update(1,d[1].id,d[1].id1,1,1,n); } printf("%d\n",ans); return 0; }
F:给定n个字符 m次操作 每次删除l r区间内出现的字符ch
题解:线段树裸题维护
#include <bits/stdc++.h> #define N 200005 using namespace std; typedef struct node{ int sum;int cnt[62];bool flag[62]; }node; node d[N<<2]; int vis[N]; int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return f*x; } void up(int root){ d[root].sum=d[root<<1].sum+d[root<<1|1].sum; for(int i=0;i<62;i++) d[root].cnt[i]=d[root<<1].cnt[i]+d[root<<1|1].cnt[i]; } void built(int root,int l,int r){ if(l==r){ d[root].sum=1;d[root].cnt[vis[l]]=1; return ; } int mid=(l+r)>>1; built(root<<1,l,mid); built(root<<1|1,mid+1,r); up(root); } void push(int root){ for(int i=0;i<62;i++){ if(d[root].flag[i]){ d[root<<1].sum-=d[root<<1].cnt[i]; d[root<<1].cnt[i]=0;d[root<<1].flag[i]=1; d[root<<1|1].sum-=d[root<<1|1].cnt[i]; d[root<<1|1].cnt[i]=0;d[root<<1|1].flag[i]=1; d[root].flag[i]=0; } } } void update(int root,int l,int r,int l1,int r1,int t){ if(d[root].cnt[t]==0) return ; if(l<=l1&&r1<=r){ d[root].flag[t]=1;d[root].sum-=d[root].cnt[t]; d[root].cnt[t]=0; return ; } int mid=(l1+r1)>>1; push(root); if(l<=mid) update(root<<1,l,r,l1,mid,t); if(r>mid) update(root<<1|1,l,r,mid+1,r1,t); up(root); } int ans1; void querty1(int root,int l,int r,int e){ if(l==r){ ans1=l; return ; } int mid=(l+r)>>1; push(root); if(e<=d[root<<1].sum) querty1(root<<1,l,mid,e); else querty1(root<<1|1,mid+1,r,e-d[root<<1].sum); up(root); } void querty2(int root,int l,int r){ if(d[root].sum==0) return ; if(l==r){ for(int i=0;i<62;i++){ if(d[root].cnt[i]==1){ ans1=i;break; } } if(ans1>=0&&ans1<=9) printf("%c",'0'+ans1); else if(ans1>=10&&ans1<=35) printf("%c",'A'+ans1-10); else printf("%c",'a'+ans1-36); return ; } int mid=(l+r)>>1; push(root); querty2(root<<1,l,mid); querty2(root<<1|1,mid+1,r); up(root); } int main(){ int n,m; n=read();m=read(); char ch; for(int i=1;i<=n;i++){ scanf(" %c",&ch); if(ch>='0'&&ch<='9') vis[i]=ch-'0'; else if(ch>='A'&&ch<='Z') vis[i]=ch-'A'+10; else vis[i]=ch-'a'+36; } built(1,1,n);int l,r; for(int i=1;i<=m;i++){ l=read();r=read();scanf("%c",&ch); int t; if(ch>='0'&&ch<='9') t=ch-'0'; else if(ch>='A'&&ch<='Z') t=ch-'A'+10; else t=ch-'a'+36; querty1(1,1,n,l);l=ans1; querty1(1,1,n,r);r=ans1; update(1,l,r,1,n,t); } querty2(1,1,n); puts(""); return 0; }