6.11 考试修改+总结
第三题至今没敢写,感觉好恐怖QAQ
今天考得好糟糕
第一题只写了10分的暴力+(k=1)20分的网络流
后来题解告诉我k>1的时候可以分治到k=1,每层分治解决方法是同k=1的
考试的时候没有注意到2^k这个比较神奇的可以分治的性质
而且自己考场上丝薄了,没有发现因为是二分图可以直接跑欧拉回路的性质,而是裸套网络流模型
第二题其实已经接近想出了题解
自己考试的时候成功证明了暴力的复杂度是线性的
但是没有想到如何寻找0-1对,然后就只能暴力用Splay维护1所在的位置了
默默祈祷数据不要太卡我的做法,结果最后只比裸暴力分多10分,只是悲桑
考后跟zcg交流一下发现维护一下hash值之后每次二分就可以找到0-1对了(考场上在想什么系列
但是这样会T或者WA(因为貌似卡自然溢出?瞎改几个base就可以了
还有一种做法是在线段树上直接劈开区间,然后如果哈希值相等的区间就不递归,否则递归下去改
时间复杂度略微有些玄学,但是跑的比hash+二分快
自己写的貌似会T一个点,不过懒得玩常数优化了
第三题貌似是弱化版的火龙果
不过LCT要维护一些奇怪的东西,考试的时候没有想出来怎么维护
后来看题解发现维护的方法类似疯狂的重心,LCT维护子树和
每次暴力删最大边看看是否可以不丢失解
但是感觉要码这样一坨东西好鬼畜啊
被莫名卡了常数,丢了20分的暴力分QAQ
最后貌似交到OJ上rank2?
%%%zcg
第一题代码:
写欧拉回路的时候写的比较鬼畜,但也只能这样写来保证O(m)的性质了(YY了好久,感谢jkxing
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cstdlib> #include<set> using namespace std; const int maxn=400010; int n,m,k,T; int deg[maxn]; struct Edge{ int u,v,id; }c[maxn],Q1[maxn],Q2[maxn]; int Ans[maxn]; int h[maxn],cnt=0; bool vis[maxn]; int check[maxn],tim; int st[maxn],top=0; struct edge{ int to,next,w; }G[maxn]; void add(int x,int y,int z=0){ ++cnt;G[cnt].to=y;G[cnt].next=h[x];G[cnt].w=z;h[x]=cnt; vis[cnt]=false; } void read(int &num){ num=0;char ch=getchar(); while(ch<'!')ch=getchar(); while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar(); } void Get_euler(int u,int f){ check[u]=tim; for(int i=h[u];i;i=h[u]){ if(vis[i]){h[u]=G[i].next;continue;} int v=G[i].to; vis[i]=vis[i^1]=true; G[i].w=G[i^1].w=f; h[u]=G[i].next; Get_euler(v,f^1); }return; } void Solve(int L,int R,int k){ if(!k)return; cnt=1;tim++;top=0; for(int i=L;i<=R;++i){ int u=c[i].u,v=c[i].v; add(u,v);add(v,u); if(check[u]!=tim)check[u]=tim,st[++top]=u; if(check[v]!=tim)check[v]=tim,st[++top]=v; }tim++; for(int i=1;i<=top;++i){ if(check[st[i]]!=tim)Get_euler(st[i],0); } int l1=0,l2=0; for(int i=L;i<=R;++i){ int now=(i-L+1)<<1; int u=c[i].id; h[c[i].u]=h[c[i].v]=0; Ans[u]=(Ans[u]<<1)|G[now].w; if(G[now].w)Q2[++l2]=c[i]; else Q1[++l1]=c[i]; } for(int i=1;i<=l1;++i)c[L+i-1]=Q1[i]; for(int i=1;i<=l2;++i)c[L+l1+i-1]=Q2[i]; Solve(L,L+l1-1,k-1);Solve(L+l1,R,k-1); } int main(){ int __size__=128<<20; char *__p__=(char*)malloc(__size__)+__size__; __asm__("movl %0, %%esp\n"::"r"(__p__)); while(scanf("%d%d",&n,&m)==2){ memset(deg,0,sizeof(deg)); for(int i=1;i<=m;++i){ read(c[i].u);read(c[i].v); c[i].id=i; deg[c[i].u]++;deg[c[i].v]++; } for(k=1;k;++k){ int mk=(1<<k); bool flag=false; for(int i=1;i<=n;++i)if(deg[i]%mk!=0||!deg[i]){flag=true;break;} if(flag)break; }k--; if(!k)printf("-1\n"); else{ memset(Ans,0,sizeof(Ans)); Solve(1,m,k); printf("%d\n",k); for(int i=1;i<=m;++i)printf("%d ",Ans[i]+1); printf("\n"); } }return 0; }
第二题代码:
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std; typedef long long LL; const int maxn=1000010; const int base=13331; int n,m,type,L,R,len,p,x,y; char s[maxn]; int sum[maxn<<2]; LL xp[maxn]; LL h[maxn<<2]; void read(int &num){ num=0;char ch=getchar(); while(ch<'!')ch=getchar(); while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar(); } void build(int o,int L,int R){ if(L==R){ h[o]=s[L]; sum[o]=h[o]-'0'; return; } int mid=(L+R)>>1; int l=(o<<1),r=(l|1); build(l,L,mid);build(r,mid+1,R); h[o]=h[l]*xp[R-mid]+h[r]; sum[o]=sum[l]+sum[r]; } void UPD(int o,int L,int R){ if(L==R){ h[o]^=1; sum[o]^=1; return; } int mid=(L+R)>>1; int l=(o<<1),r=(l|1); if(p<=mid)UPD(l,L,mid); else UPD(r,mid+1,R); h[o]=h[l]*xp[R-mid]+h[r]; sum[o]=sum[l]+sum[r]; } LL ask(int o,int L,int R){ if(L>=x&&R<=y)return h[o]; int mid=(L+R)>>1; if(y<=mid)return ask(o<<1,L,mid); else if(x>mid)return ask(o<<1|1,mid+1,R); else{ LL A=ask(o<<1,L,mid); LL B=ask(o<<1|1,mid+1,R); return A*xp[min(y,R)-mid]+B; } } int ask_S(int o,int L,int R){ if(L>=x&&R<=y)return sum[o]; int mid=(L+R)>>1; if(y<=mid)return ask_S(o<<1,L,mid); else if(x>mid)return ask_S(o<<1|1,mid+1,R); else return ask_S(o<<1,L,mid)+ask_S(o<<1|1,mid+1,R); } int main(){ freopen("and.in","r",stdin); freopen("and.out","w",stdout); read(n);read(m); scanf("%s",s+1); xp[0]=1; for(int i=1;i<=n;++i)xp[i]=xp[i-1]*base; build(1,1,n); while(m--){ read(type); if(type==1){ read(L);read(R);read(len); int l=1,r=len; while(true){ while(l<r){ int mid=(l+r)>>1; x=L;y=L+mid-1; LL A=ask(1,1,n); x=R;y=R+mid-1; LL B=ask(1,1,n); if(A==B)l=mid+1; else r=mid; } x=L+r-1;y=R+r-1; int A=s[x]-'0',B=s[y]-'0'; if(A==B)break; if(A==1)s[x]='0',p=x,UPD(1,1,n); else s[y]='0',p=y,UPD(1,1,n); l=r;r=len; } }else if(type==2){ read(L);p=L; if(s[L]=='1')s[L]='0'; else s[L]='1'; UPD(1,1,n); }else{ read(L);read(R);read(len); x=L;y=R; int now=ask_S(1,1,n); if(len==1)printf("%d\n",now); else printf("%d\n",R-L+1-now); } }return 0; }
第三题看看zcg他们能不能搞出来吧
感觉自己要写的话一个晚上药丸啊