2019中山大学程序设计竞赛(重现赛)
02,如果没有三角形,那么数列是斐波拉契数列级别增长,所以个数<50;
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=5000010; int a[maxn]; int main(){ //freopen("input.txt","r",stdin); int N; while(~scanf("%d",&N)){ rep(i,1,N) scanf("%d", &a[i]); bool F=0; if(N<100){ sort(a+1,a+N+1); rep(i,1,N-2){ if(a[i]+a[i+1]>a[i+2]){ F=1; break; } } } else F=true; puts(F?"YES":"NO"); } return 0; }
04,两次前缀和,第一次前缀和得到被多少个覆盖; 第二次,把非0的前缀和贡献1,再前缀和。(或数状数组。
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=20000010; int N,M,a[maxn],b[maxn]; void add(int i,int j,int val) { if(i>N||j>M) return ; a[(i-1)*M+j]+=val; } int query(int i,int j) { if(i==0||j==0) return 0; return a[(i-1)*M+j]; } int main() { int P,Q,x1,x2,y1,y2; while(~scanf("%d%d",&N,&M)){ rep(i,1,N*M) a[i]=0; scanf("%d",&P); rep(i,1,P){ scanf("%d%d%d%d",&x1,&y1,&x2,&y2); add(x1,y1,1); add(x1,y2+1,-1); add(x2+1,y1,-1); add(x2+1,y2+1,1); } rep(i,1,N) rep(j,1,M){ a[(i-1)*M+j]=query(i,j-1)+query(i-1,j)-query(i-1,j-1)+a[(i-1)*M+j]; } rep(i,1,N) rep(j,1,M){ if(a[(i-1)*M+j]!=0) a[(i-1)*M+j]=1; } rep(i,1,N) rep(j,1,M){ a[(i-1)*M+j]=query(i,j-1)+query(i-1,j)-query(i-1,j-1)+a[(i-1)*M+j]; } scanf("%d",&Q); rep(i,1,Q){ scanf("%d%d%d%d",&x1,&y1,&x2,&y2); int res=query(x2,y2)+query(x1-1,y1-1)-query(x1-1,y2)-query(x2,y1-1); if(res==(x2-x1+1)*(y2-y1+1)) printf("YES\n"); else printf("NO\n"); } } return 0; }
05
#include <cstdio> #include <algorithm> #include <cmath> #include <set> #include <cstring> using namespace std; char s[300005]; int n,i,a,b,c,ans[105],m,j; int main(){ scanf("%s",s); n=strlen(s)/3; for(j=0;j<n;j++){ a=s[j*3];b=s[j*3+1];c=s[j*3+2]; for(i=1;i<=8;i++)ans[i]=a&1,a>>=1; for(i=9;i<=16;i++)ans[i]=b&1,b>>=1; for(i=17;i<=24;i++)ans[i]=c&1,c>>=1; m=0;for(i=1;i<=6;i++)m<<=1,m|=ans[i];printf("%d ",m); m=0;for(i=7;i<=12;i++)m<<=1,m|=ans[i];printf("%d ",m); m=0;for(i=13;i<=18;i++)m<<=1,m|=ans[i];printf("%d ",m); m=0;for(i=19;i<=24;i++)m<<=1,m|=ans[i];printf("%d ",m); } return 0; }
08
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=20000010; int a[105][105][105],b,x,y,z,X,Y,Z,ans; int main(){ while(scanf("%d%d%d",&X,&Y,&Z)!=EOF){ for(x=1;x<=X;x++) for(y=1;y<=Y;y++) for(z=1;z<=Z;z++)a[x][y][z]=1; for(x=1;x<=X;x++)for(y=1;y<=Y;y++){ scanf("%d",&b); if(!b)for(z=1;z<=Z;z++)a[x][y][z]=0; } for(y=1;y<=Y;y++)for(z=1;z<=Z;z++){ scanf("%d",&b); if(!b)for(x=1;x<=X;x++)a[x][y][z]=0; } for(z=1;z<=Z;z++) for(x=1;x<=X;x++){ scanf("%d",&b); if(!b)for(y=1;y<=Y;y++)a[x][y][z]=0; } ans=0; for(x=1;x<=X;x++) for(y=1;y<=Y;y++) for(z=1;z<=Z;z++)ans+=a[x][y][z]; printf("%d\n",ans); } return 0; }
09
#include <bits/stdc++.h> #define IOS ios::sync_with_stdio(false); #define Accepted 0 using namespace std; typedef long long ll; const int maxn = 1000000 + 10; const int INF = 1e9 + 7; const int MOD = 1e9 + 7; const double eps = 1e-10; const double pi = acos(-1); int T, cases, n, m, k; char Map[110][110]; int main() { while(scanf("%d%d%d", &n, &m, &k) != EOF) { for(int i = 0; i < n; i++)scanf("%s", Map[i]); for(int i = 0; i < n; i++) { for(int c = 0; c < k; c++) { for(int j = 0; j < m; j++) { for(int d = 0; d < k; d++) { putchar(Map[i][j]); } } puts(""); } } } return Accepted; }
07。。。wa了
11,维护每个点的Left,Right,差值是贡献。 吉司机线段树。 (我好像zz了,维护一个即可,等效的。
但是好像有更优秀的做法。待补
#include<bits/stdc++.h> #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=2000010; int mx[2][maxn],mc[2][maxn],se[2][maxn]; ll sum[2][maxn]; void pushdown(int p,int Now) { if(mx[p][Now]<mx[p][Now<<1]){ sum[p][Now<<1]-=(ll)(mx[p][Now<<1]-mx[p][Now])*mc[p][Now<<1]; mx[p][Now<<1]=mx[p][Now]; } if(mx[p][Now]<mx[p][Now<<1|1]){ sum[p][Now<<1|1]-=(ll)(mx[p][Now<<1|1]-mx[p][Now])*mc[p][Now<<1|1]; mx[p][Now<<1|1]=mx[p][Now]; } } void pushup(int p,int Now) { sum[p][Now]=sum[p][Now<<1]+sum[p][Now<<1|1]; mx[p][Now]=max(mx[p][Now<<1],mx[p][Now<<1|1]); if(mx[p][Now<<1]==mx[p][Now<<1|1]){ mc[p][Now]=mc[p][Now<<1]+mc[p][Now<<1|1]; se[p][Now]=max(se[p][Now<<1],se[p][Now<<1|1]); } else { if(mx[p][Now<<1]>mx[p][Now<<1|1]){ mc[p][Now]=mc[p][Now<<1]; se[p][Now]=max(mx[p][Now<<1|1],se[p][Now<<1]); } else { mc[p][Now]=mc[p][Now<<1|1]; se[p][Now]=max(mx[p][Now<<1],se[p][Now<<1|1]); } } } void build(int Now,int L,int R) { if(L==R){ sum[0][Now]=mx[0][Now]=L; mc[0][Now]=1; se[0][Now]=-maxn; sum[1][Now]=mx[1][Now]=-L; mc[1][Now]=1; se[1][Now]=-maxn; return ; } int Mid=(L+R)>>1; build(Now<<1,L,Mid); build(Now<<1|1,Mid+1,R); pushup(0,Now); pushup(1,Now); } ll query(int p,int Now,int L,int R,int l,int r){ if(l<=L&&r>=R) return sum[p][Now]; int Mid=(L+R)>>1; ll res=0; pushdown(p,Now); if(l<=Mid) res+=query(p,Now<<1,L,Mid,l,r); if(r>Mid) res+=query(p,Now<<1|1,Mid+1,R,l,r); return res; } void update(int p,int Now,int L,int R,int l,int r,int x) { //cout<<L<<" "<<R<<" "<<Now<<endl; if(mx[p][Now]<=x) return ; if(l<=L&&r>=R){ if(se[p][Now]<x){ sum[p][Now]-=(ll)mc[p][Now]*(mx[p][Now]-x); mx[p][Now]=x; return ; } } int Mid=(L+R)>>1; pushdown(p,Now); if(l<=Mid) update(p,Now<<1,L,Mid,l,r,x); if(r>Mid) update(p,Now<<1|1,Mid+1,R,l,r,x); pushup(p,Now); } int main() { int N,M,L,R; while(~scanf("%d%d",&N,&M)){ build(1,1,N); rep(i,1,M){ scanf("%d%d",&L,&R); ll ans=query(0,1,1,N,L,R)+query(1,1,1,N,L,R); update(0,1,1,N,L,R,L); update(1,1,1,N,L,R,-R); ll res=query(0,1,1,N,L,R)+query(1,1,1,N,L,R); //cout<<res<<" "<<ans<<endl; printf("%lld\n",(ans-res)/2); } } return 0; }
It is your time to fight!