比赛的时候只过了ABC题,F题爆了三发,TLE,后来发现F题把<=1改成<=2就A了,┭┮﹏┭┮
A:n个格子,k个有水,每次有水的格子会往左右倒水,问多少轮后所有格子都有水。
题解:模拟。。
#include<cstdio> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #include<map> #include<set> #include<queue> #include<vector> #define mp make_pair using namespace std; typedef long long LL; typedef pair<int,int> pa; const int N=206; int n,a[N]; bool b[N],c[N]; int Write[20],WRI; void judge(){freopen(".in","r",stdin);freopen(".out","w",stdout);} int read(){int d=0,f=1; char c=getchar(); while (c<'0'||c>'9'){if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') d=d*10+c-48,c=getchar(); return d*f;} void write(int x){if (!x){putchar('0'); return;}if (x<0) putchar('-'),x=-x;for (WRI=1;x;x/=10,WRI++) Write[WRI]=x%10;for (int i=WRI-1;i;i--) putchar((char)(Write[i]+48));} int main() { //judge(); int T=read(); while (T--) { n=read(); int k=read(); for (int i=1;i<=200;i++) b[i]=0; for (int i=1;i<=k;i++) b[read()]=1; int ans=0; for (;;ans++) { bool bo=1; for (int i=1;i<=n;i++) if (!b[i]) bo=0; if (bo) break; for (int i=1;i<=n;i++) if (b[i]) { if (i-1) c[i-1]=1; if (i+1<=n) c[i+1]=1; c[i]=1; } for (int i=1;i<=n;i++) b[i]=c[i],c[i]=0; } printf("%d\n",ans+1); } return 0; }
B:有n(n<=1000)个学生,第i个学生在l[i]时刻来到queue最后,同一时刻来的学生编号小的在前,每个时刻队头的学生能拿到tea,若第i个学生r[i]时刻不能拿到tea,他就会离开队伍。问每个学生拿到tea的时刻(不能拿到的输出0)
题解:一开始没想清楚就写了,WA,改完后发现自己是个ZZ,也算是模拟题吧。。。
#include<cstdio> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #include<cstring> #include<map> #include<set> #include<queue> #include<vector> #define mp make_pair using namespace std; typedef long long LL; typedef pair<int,int> pa; const int N=1010; struct node{int x,y,id;}a[N]; int n,T,h,t,q[N],ans[N]; int Write[20],WRI; void judge(){freopen(".in","r",stdin);freopen(".out","w",stdout);} int read(){int d=0,f=1; char c=getchar(); while (c<'0'||c>'9'){if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') d=d*10+c-48,c=getchar(); return d*f;} void write(int x){if (!x){putchar('0'); return;}if (x<0) putchar('-'),x=-x;for (WRI=1;x;x/=10,WRI++) Write[WRI]=x%10;for (int i=WRI-1;i;i--) putchar((char)(Write[i]+48));} bool cmp(node a,node b){return a.x<b.x||a.x==b.x&&a.id<b.id;} int main() { //judge(); int T=read(); while (T--) { n=read(); memset(a,0,sizeof a); memset(q,0,sizeof q); for (int i=1;i<=n;i++) a[i].x=read(),a[i].y=read(); for (int i=1;i<=n;i++) a[i].id=i; sort(a+1,a+1+n,cmp); int tt=a[1].x; bool bo=0; for (int p=1;p<=n;p++) { int x=p; if (tt>a[x].y) ans[x]=0; else { if (tt<a[x].x) tt=a[x].x; ans[x]=tt; tt++; } } for (int i=1;i<=n;i++) printf("%d ",ans[i]); puts(""); } return 0; }
C:给一个n个数的排列(n<=200000),告诉你每个位置能否与后一位交换,问能否通过若干次交换使序列有序。
题解:从大到小枚举,可行的话必须要这个数当前位置到应在位置-1都是可交换的,做完了。
#include<cstdio> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #include<map> #include<set> #include<queue> #include<vector> #define mp make_pair using namespace std; typedef long long LL; typedef pair<int,int> pa; const int N=200010; int n,a[N],b[N],sum[N]; char s[N]; int Write[20],WRI; void judge(){freopen(".in","r",stdin);freopen(".out","w",stdout);} int read(){int d=0,f=1; char c=getchar(); while (c<'0'||c>'9'){if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') d=d*10+c-48,c=getchar(); return d*f;} void write(int x){if (!x){putchar('0'); return;}if (x<0) putchar('-'),x=-x;for (WRI=1;x;x/=10,WRI++) Write[WRI]=x%10;for (int i=WRI-1;i;i--) putchar((char)(Write[i]+48));} int main() { //judge(); n=read(); for (int i=1;i<=n;i++) a[i]=read(),b[a[i]]=i; scanf("%s",s+1); for (int i=n;i>=1;i--) sum[i]=sum[i+1]+s[i]-'0'; for (int i=n;i>=1;i--) if (i>b[i]&&sum[b[i]]-sum[i]!=i-b[i]) { puts("NO"); return 0; } puts("YES"); return 0; }
E:有一个n个点m条边的无向图,求其补图的联通块个数及每个块的大小(n,m<=200000)
题解:bfs,每次bfs时,设u=q.front(),将原图中与u相连的点标记为与u相连,这样剩下的点就是补图中与u相连的点,将它们加入联通块和队列,用链表优化。
#include<cstdio> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #include<map> #include<set> #include<queue> #include<vector> #define mp make_pair using namespace std; typedef long long LL; typedef pair<int,int> pa; const int N=200010; struct E{int to,nxt;}e[N<<1]; int n,m,head[N],cnt,l[N],r[N],ans[N],ans_cnt,fa[N]; bool b[N]; int Write[20],WRI; void judge(){freopen(".in","r",stdin);freopen(".out","w",stdout);} int read(){int d=0,f=1; char c=getchar(); while (c<'0'||c>'9'){if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') d=d*10+c-48,c=getchar(); return d*f;} void write(int x){if (!x){putchar('0'); return;}if (x<0) putchar('-'),x=-x;for (WRI=1;x;x/=10,WRI++) Write[WRI]=x%10;for (int i=WRI-1;i;i--) putchar((char)(Write[i]+48));} void add(int x,int y){e[++cnt]=(E){y,head[x]}; head[x]=cnt;} void addedge(int x,int y){add(x,y); add(y,x);} void del(int x){b[x]=1; r[l[x]]=r[x]; l[r[x]]=l[x];} void bfs(int ljj) { queue<int>q; int sum=1; q.push(ljj); while (!q.empty()) { int u=q.front(); q.pop(); for (int i=head[u];i;i=e[i].nxt) { int v=e[i].to; fa[v]=u; } for (int i=r[0];i<=n;i=r[i]) if (fa[i]!=u&&!b[i]) { q.push(i); del(i); sum++; } } ans[++ans_cnt]=sum; } int main() { //judge(); n=read(); m=read(); for (int i=1;i<=m;i++) addedge(read(),read()); for (int i=0;i<=n;i++) l[i]=i-1,r[i]=i+1; for (int i=1;i<=n;i=r[i]) if (!b[i]) { del(i); bfs(i); } sort(ans+1,ans+1+ans_cnt); write(ans_cnt); puts(""); for (int i=1;i<=ans_cnt;i++) write(ans[i]),putchar(' '); return 0; }
F:设D(n)表示n的因数个数,给n个数,q次操作,1 l r表示将[l,r]的每个数a[i]变为D(a[i]),2 l r表示输出sum(l,r)。(n,q<=3E5,a[i]<=1E6)
题解:套路题,线段树,x变为D(x)的次数不会很多,修改就暴力下去,每个节点记录其代表区间是否全部<=2,遇到标记了的区间就不用下去了,查询直接做。比赛的时候脑子不清楚,写了<=1,愉快地T了。。。
#include<cstdio> typedef long long LL; const int N=300010,M=1000010; struct node{int l,r; LL s; bool b;}a[N<<2]; int n,m,f[M]; int Write[20],WRI; inline int read(){int d=0,f=1; char c=getchar(); while (c<'0'||c>'9'){if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') d=d*10+c-48,c=getchar(); return d*f;} inline void write(LL x){if (!x){putchar('0'); return;}if (x<0) putchar('-'),x=-x;for (WRI=1;x;x/=10,WRI++) Write[WRI]=x%10;for (int i=WRI-1;i;i--) putchar((char)(Write[i]+48));} inline void build(int i,int l,int r) { a[i].l=l; a[i].r=r; a[i].b=0; if (l==r) {a[i].s=read(); if (a[i].s<=2) a[i].b=1; return;} int mid=(l+r)>>1; build(i<<1,l,mid); build(i<<1|1,mid+1,r); a[i].s=a[i<<1].s+a[i<<1|1].s; a[i].b=a[i<<1].b&&a[i<<1|1].b; } inline void update(int i,int l,int r) { if (a[i].b) return; if (a[i].l==a[i].r) {a[i].s=f[a[i].s]; if (a[i].s<=2) a[i].b=1; return;} int mid=(a[i].l+a[i].r)>>1; if (r<=mid) update(i<<1,l,r); else if (l>mid) update(i<<1|1,l,r); else update(i<<1,l,mid),update(i<<1|1,mid+1,r); a[i].s=a[i<<1].s+a[i<<1|1].s; a[i].b=a[i<<1].b&&a[i<<1|1].b; } inline LL query(int i,int l,int r) { if (l<=a[i].l&&a[i].r<=r) return a[i].s; int mid=(a[i].l+a[i].r)>>1; if (r<=mid) return query(i<<1,l,r); else if (l>mid) return query(i<<1|1,l,r); else return query(i<<1,l,mid)+query(i<<1|1,mid+1,r); } int main() { n=read(); m=read(); for (int i=1;i<=1000000;i++) for (int j=1;i*j<=1000000;j++) f[i*j]++; build(1,1,n); while (m--) { int op=read(),l=read(),r=read(); if (op==1) update(1,l,r); else printf("%lld\n",query(1,l,r)); } return 0; }