省選磨泥34
阿新 • • 發佈:2022-03-18
可能是時運不濟,導致我菜到家了...
AK啊三個人,啊啊啊我只有一半的分
一眼切第一題,第二題整個人發憷,第三題想打部分分打完了發現假了...
T1 無向圖
直接可撤銷線性基,據說有直接撤銷版本的單\(log\),我我是線段樹分治
AC_code
#include<bits/stdc++.h> using namespace std; #define fo(i,x,y) for(int i=(x);i<=(y);i++) #define fu(i,x,y) for(int i=(x);i>=(y);i--) int read(){ int s=0,t=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();} while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();} return s*t; } const int N=1e5+5; int m,q,ans[N]; struct BAS{ int lba[35],cba; int ins(int x){ fu(i,30,0)if(x>>i&1){ if(lba[i])x^=lba[i]; else { lba[i]=x;cba++; return i; } } return -1; } void ers(int x){if(x==-1)return ;lba[x]=0;cba--;} }bas; struct XDS{ #define ls x<<1 #define rs x<<1|1 vector<int> vec[N*4]; void ins(int x,int l,int r,int ql,int qr,int v){ if(ql<=l&&r<=qr)return vec[x].push_back(v),void(); int mid=l+r>>1; if(ql<=mid)ins(ls,l,mid,ql,qr,v); if(qr>mid)ins(rs,mid+1,r,ql,qr,v); return ; } int sta[N],top; void dfs(int x,int l,int r){ // cerr<<x<<" "<<l<<" "<<r<<" "<<bas.cba<<endl; int s=top; for(int i:vec[x])sta[++top]=bas.ins(i); if(l==r){ ans[l]=(1<<bas.cba); while(top>s)bas.ers(sta[top--]); return ; } int mid=l+r>>1; dfs(ls,l,mid); dfs(rs,mid+1,r); while(top>s)bas.ers(sta[top--]); } #undef ls #undef rs }xds; map<int,int> mp; signed main(){ freopen("xor.in","r",stdin); freopen("xor.out","w",stdout); m=read();q=read(); fo(i,1,q){ int tp=read(),x=read(); if(tp==1)mp[x]=i; else xds.ins(1,1,q,mp[x],i-1,x),mp.erase(x); } for(pair<int,int> i:mp)xds.ins(1,1,q,i.second,q,i.first); xds.dfs(1,1,q); fo(i,1,q)printf("%d\n",ans[i]); return 0; }
T2 加與乘
A要是最後一手,那A必勝
如果B是最後一手的話,那麼當A操作時如果兩個相鄰的偶數之間都有奇數個奇數,包括和開頭和末尾,那A必輸
那麼如果是A先手直接判斷就好了
如果是B先手,判斷是不是隻有一個區間是不合法的就好了
考場上看出來這個結論了,但是沒有分A先手還是B先手,其實就是不會
AC_code
#include<bits/stdc++.h> using namespace std; #define fo(i,x,y) for(int i=(x);i<=(y);i++) #define fu(i,x,y) for(int i=(x);i>=(y);i--) int read(){ int s=0,t=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();} while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();} return s*t; } const int N=1e5+5; int T,n[11],m[11],a[11][N]; int mx,dp[21][1<<20][2],sum[1<<20]; inline int get(int l,int r){return (1<<l+1)-(1<<r);} void init_dp(){ dp[1][1][0]=dp[1][1][1]=1; dp[1][0][0]=dp[1][0][1]=0; fo(len,2,20)fo(s,0,(1<<len)-1){ fo(i,0,1){ bool flag=i^1; fo(j,1,len-1){int t; int t1=(s>>j)&1,t2=(s>>j-1)&1; t=((s&get(len-1,j+1))>>1)|((t1&t2)<<j-1)|(s&get(j-2,0)); if(dp[len-1][t][i^1]==i)flag=i; t=((s&get(len-1,j+1))>>1)|((t1^t2)<<j-1)|(s&get(j-2,0)); if(dp[len-1][t][i^1]==i)flag=i; } dp[len][s][i]=flag; } } } void spj(int id){int now=0; fo(i,1,n[id])now=(now<<1)+a[id][i]; printf(dp[n[id]][now][m[id]]?"B\n":"A\n"); } signed main(){ freopen("game.in","r",stdin); freopen("game.out","w",stdout); T=read();bool fl=false; fo(tt,1,T){ n[tt]=read();m[tt]=read(); fo(i,1,n[tt])a[tt][i]=read()&1; if(n[tt]<=20)fl=true,mx=max(mx,n[tt]); } if(fl)init_dp(); fo(tt,1,T){ if(((n[tt]-1)&1)!=m[tt]){printf("A\n");continue;} if(n[tt]<=20){spj(tt);continue;} int las=0,sm=0;int flag=0; fo(i,1,n[tt])if(!a[tt][i]){ if(i-las&1)flag++; las=i;sm++; } if(n[tt]+1-las&1)flag++; if(!m[tt])printf(!flag?"B\n":"A\n"); else if(m[tt])printf(flag==1?"B\n":"A\n"); } return 0; }
T3 數顏色
發現就是統計一個點被覆蓋了但是他到他爹的邊沒有被覆蓋的個數
於是我們分機器人考慮,一個機器人的貢獻就是在lca處給出的
如果貢獻不見了,那就是被其他的機器人路線給覆蓋了
我們想要找前驅和後繼,但是發現如果有兩個一樣的機器人,那就互相找不到了
於是我們讓後面的可以找到前面的,就找前驅的時候覆蓋lca,後繼的時候就不覆蓋了
AC_code
#include<bits/stdc++.h> using namespace std; #define fo(i,x,y) for(int i=(x);i<=(y);i++) #define fu(i,x,y) for(int i=(x);i>=(y);i--) int read(){ int s=0,t=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();} while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();} return s*t; } const int N=1e5+5; int n,m,q,ans[N]; struct A{int x,y,lca;}a[N]; struct B{int l,r,id;}b[N]; bool com(B a,B b){return a.l<b.l;} struct E{int to,nxt;}e[N*2]; int head[N],rp; void add_edg(int x,int y){e[++rp].to=y;e[rp].nxt=head[x];head[x]=rp;} struct XDS{ #define ls x<<1 #define rs x<<1|1 int who[N*4],two[N*4]; void pushdown(int x){ who[ls]=two[ls]=two[x]; who[rs]=two[rs]=two[x]; two[x]=0;return ; } void build(int x,int l,int r){ who[x]=two[x]=0; if(l==r)return ; int mid=l+r>>1; build(ls,l,mid); build(rs,mid+1,r); return ; } void ins(int x,int l,int r,int ql,int qr,int v){ if(ql>qr)return ; if(ql<=l&&r<=qr)return who[x]=two[x]=v,void(); int mid=l+r>>1;if(two[x])pushdown(x); if(ql<=mid)ins(ls,l,mid,ql,qr,v); if(qr>mid)ins(rs,mid+1,r,ql,qr,v); } int query(int x,int l,int r,int pos){ if(l==r)return who[x]; int mid=l+r>>1;if(two[x])pushdown(x); if(pos<=mid)return query(ls,l,mid,pos); else return query(rs,mid+1,r,pos); } #undef ls #undef rs }xds; int siz[N],son[N],top[N],dep[N],fa[N]; void dfs_fi(int x,int f){ fa[x]=f;dep[x]=dep[f]+1; siz[x]=1;son[x]=0; for(int i=head[x];i;i=e[i].nxt){ int y=e[i].to; if(y==f)continue; dfs_fi(y,x);siz[x]+=siz[y]; if(!son[x]||siz[y]>siz[son[x]])son[x]=y; } } int dfn[N],idf[N],cnt; void dfs_se(int x,int f){ top[x]=f;dfn[x]=++cnt;idf[cnt]=x; if(son[x])dfs_se(son[x],f); for(int i=head[x];i;i=e[i].nxt){ int y=e[i].to; if(y==fa[x]||y==son[x])continue; dfs_se(y,y); } } int LCA(int x,int y){ while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]])swap(x,y); x=fa[top[x]]; }return dep[x]<dep[y]?x:y; } void change1(int x,int y,int v){ while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]])swap(x,y); xds.ins(1,1,n,dfn[top[x]],dfn[x],v); x=fa[top[x]]; } if(dep[x]>dep[y])swap(x,y); xds.ins(1,1,n,dfn[x],dfn[y],v); } void change2(int x,int y,int v){ while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]])swap(x,y); xds.ins(1,1,n,dfn[top[x]],dfn[x],v); x=fa[top[x]]; } if(dep[x]>dep[y])swap(x,y); xds.ins(1,1,n,dfn[x]+1,dfn[y],v); } int ll[N],rr[N]; struct BIT{ int tr[N]; void insert(int x,int v){ for(int i=x;i<=n;i+=(i&-i))tr[i]+=v; } int query(int x){ int ret=0; for(int i=x;i;i-=(i&-i))ret+=tr[i]; return ret; } void ins(int l,int r,int v){ // cerr<<"ins"<<" "<<l<<" "<<r<<" "<<v<<endl; insert(l,v);insert(r+1,-v); } }bit; vector<int> del[N]; signed main(){ freopen("tree.in","r",stdin); freopen("tree.out","w",stdout); n=read();m=read();q=read(); fo(i,1,n-1){ int x=read(),y=read(); add_edg(x,y);add_edg(y,x); } dfs_fi(1,0);dfs_se(1,1); fo(i,1,m)a[i].x=read(),a[i].y=read(),a[i].lca=LCA(a[i].x,a[i].y); fo(i,1,q)b[i].l=read(),b[i].r=read(),b[i].id=i; fo(i,1,m){ ll[i]=xds.query(1,1,n,dfn[a[i].lca]); change1(a[i].x,a[i].y,i); }xds.build(1,1,n); fu(i,m,1){ rr[i]=xds.query(1,1,n,dfn[a[i].lca]); change2(a[i].x,a[i].y,i); } sort(b+1,b+q+1,com);b[q+1].l=m+1; // fo(i,1,m)cerr<<ll[i]<<" "<<rr[i]<<endl; fu(qq,q,1){ fu(i,b[qq+1].l-1,b[qq].l){ // cerr<<qq<<" "<<i<<" "<<b[qq].l<<endl; for(int x:del[i]){ if(rr[x])bit.ins(x,rr[x]-1,-1); else bit.ins(x,n,-1); } if(rr[i])bit.ins(i,rr[i]-1,1); else bit.ins(i,n,1); if(ll[i])del[ll[i]].push_back(i); } // cerr<<"ans"<<" "<<b[qq].id<<" "<<b[qq].l<<" "<<b[qq].r<<" "<<bit.query(b[qq].r)<<endl; ans[b[qq].id]=bit.query(b[qq].r); } fo(i,1,q)printf("%d\n",ans[i]); }