1007
簡單博弈,隊友做的
#include<bits/stdc++.h> using namespace std; const int N=2e5; int n,a[N+5],b[N+5],A,B; bool vis[N+5]; inline int read() { int x=0;bool f=1;char ch=getchar(); for(;ch<'0'||ch>'9';ch=getchar())f^=(ch=='-'); for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+(ch^48); return f?x:-x; } void Kafka() { n=read(); for(int i=1;i<=n;++i) vis[i]=0; A=0;for(int i=1;i<=n;++i) A+=(vis[a[i]=read()]),vis[a[i]]=1; for(int i=1;i<=n;++i) vis[i]=0; B=0;for(int i=1;i<=n;++i) B+=(vis[b[i]=read()]),vis[b[i]]=1; if(A==0&&B==0) puts("sha7dow"); else puts(A>=B?"shuishui":"sha7dow"); } signed main() { for(int T=read();T--;) Kafka(); return 0; }
1003
詐騙題,合併順序根本不會影響答案(之前見過類似的),模擬一遍就好
#include<bits/stdc++.h> using namespace std; #define int long long const int mod = 998244353; const int N = 1e6+5; int w[N]; void solve(){ int n;cin>>n; for(int i=1;i<=n;i++) cin>>w[i]; int ans=0; for(int r=n,i=1;i<=n-1;i++,r--){ if(r==1) break; ans+=w[1]*w[r]%mod*((w[r]+w[1])%mod)%mod ; ans%=mod; w[1]+=w[r]; w[1]%=mod; } cout<<ans<<"\n"; } signed main() { ios_base::sync_with_stdio(false); cin.tie(0);cout.tie(0); int t;cin>>t; while(t--) solve(); return 0; }
1005
沒想得很明白,賽時亂搞沒過,最後倆隊友一起做的
#include<bits/stdc++.h> using namespace std; #define int long long inline int read() { int x=0;bool f=1;char ch=getchar(); for(;ch<'0'||ch>'9';ch=getchar())f^=(ch=='-'); for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+(ch^48); return f?x:-x; } int k,x,y,t; bool all(){ if (k<=x) return false; if(y>=2*x) return true; return t*x-k+(t-1)*(y%x)>=x; } void Kafka() { cin>>k>>x>>y; if(x>y) swap(x,y); t=(k+x-1)/x; if (all()) cout << "Yes\nYes\n"; else{ if (t&1) cout << "Yes\nNo\n"; else cout << "No\nYes\n"; } } signed main() { ios_base::sync_with_stdio(false); cin.tie(0);cout.tie(0); int T;cin>>T; while(T--) Kafka(); return 0; }
1001
一個顯然的結論是k不重要,每位都是獨立的
接下來一個顯然的想法是構造,儘可能讓每個子樹內01數量均等
如果不均等的話把奇數數目的子樹個數算一下,抽一半出來強制為1,另一半強制為0
最後01可以翻轉,答案再*2
#include<bits/stdc++.h> using namespace std; const int N=2e5,mod=998244353; inline int add(int x,int y){return (x+=y)>=mod?x-mod:x;} inline int sub(int x,int y){return (x-=y)<0?x+mod:x;} inline int mul(int x,int y){return 1LL*x*y%mod;} inline int qpow(int x,int y){int res=1;for(;y;y>>=1,x=mul(x,x))if(y&1)res=mul(res,x);return res;} int fac[N+5],inv[N+5]; inline int C(int x,int y){return x>y?0:mul(fac[y],mul(inv[x],inv[y-x]));} int n,k,f[N+5],Siz[N+5]; vector<int> ver[N+5]; inline int read() { int x=0;bool f=1;char ch=getchar(); for(;ch<'0'||ch>'9';ch=getchar())f^=(ch=='-'); for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+(ch^48); return f?x:-x; } void dfs(int x,int fa) { Siz[x]=1,f[x]=1; int sum=1; for(auto y:ver[x]) { if(y==fa) continue; dfs(y,x); Siz[x]+=Siz[y]; f[x]=mul(f[x],f[y]); sum+=Siz[y]&1; } f[x]=mul(f[x],C(sum>>1,sum)); } void Kafka() { n=read(),k=read(); for(int i=1;i<=n;++i) ver[i].clear(); for(int i=2;i<=n;++i) ver[read()].push_back(i); dfs(1,0); // for(int i=1;i<=n;++i) printf("f[%d]=%d\n",i,f[i]); printf("%d\n",qpow(mul((Siz[1]&1)?2:1,f[1]),k)); } signed main() { fac[0]=1;for(int i=1;i<=N;++i) fac[i]=mul(i,fac[i-1]); inv[N]=qpow(fac[N],mod-2);for(int i=N-1;~i;--i) inv[i]=mul(i+1,inv[i+1]); for(int T=read();T--;) Kafka(); return 0; } /* 1 5 1 1 1 1 2 18 */
1002
資料假了,純暴力做法才跑了時限一半,比正解還快
#include<bits/stdc++.h> using namespace std; const int N = 100001; int p[N]; int cnt; int l,r; vector<int> G[N]; int w2v[N]; bool S[N]; void dfs(int now){ cnt--; S[now]=1; bool flag=0; for(int child:G[now]){ if(!S[child]){ if(p[child]<=r&&p[child]>=l){ dfs(child); flag=1; } } } } int main(){ ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t;cin>>t; while(t--){ int n;cin>>n; for(int i=1;i<=n;i++){ cin>>p[i]; w2v[p[i]]=i; } int x,y; for(int i=0;i<n-1;i++){ cin>>x>>y; G[x].push_back(y); G[y].push_back(x); } int m;cin>>m; int oprt; for(int i=0;i<m;i++){ cin>>oprt>>x>>y; if(oprt==1){ int t=p[x]; p[x]=p[y]; p[y]=t; w2v[p[x]]=x; w2v[p[y]]=y; } else { memset(S,0,n+1); l=x; r=y; cnt=r-l+1; dfs(w2v[l]); if(cnt==0){ cout<<"Yes"<<"\n"; } else cout<<"No"<<"\n"; } } } }
但是我們要追求正解是不~
考慮區間[l,r]內所有點中深度最深的點,一定是路徑端點,另一個路徑端點可能是次深點,也可能是最深點的祖先
可以把求最深點和次深點放線上段樹區間合併時維護,具體細節看線段樹內的merge( )
確定了端點後要判斷的就是路徑長度是否=r-l+1以及路徑最小值是否=l,最大值是否等於r,這些可以用樹鏈剖分做
所以做法就是:
以點權為下標維護一顆線段樹,線段樹的節點資訊有當前區間內最深點、次深點、次深點如果為-1的話另外一個端點(也就是lca)
再樹剖維護路徑最大值和最小值
注意:區間合併時求lca要用st表法,用倍增法會多一個log
#include<bits/stdc++.h> using namespace std; #define mid ((l+r)>>1) #define ls (rt<<1) #define rs (rt<<1|1) int n ; const int N = 1e5+5; vector<int>e[N]; int lg[N],p[N],invp[N],invdfn[N],siz[N],fa[N],dep[N],cnt,id[N],top[N],lcaf[N][20],son[N],mx[N<<2],mi[N<<2]; int get(int x, int y) {return id[x] < id[y] ? x : y;} int LCA(int u,int v){ if(u == v) return u; if((u = id[u]) > (v = id[v])) swap(u, v); int d = __lg(v - u++); return get(lcaf[u][d], lcaf[v - (1 << d) + 1][d]); } void dfs1(int u,int f){ cnt++;// dfs order id[u]=cnt;// id:dfn lcaf[id[u]][0] = f; siz[u]=1; fa[u]=f; dep[u]=dep[f]+1; int maxson=-1; for(auto to:e[u]){ if(to==f) continue; dfs1(to,u); siz[u]+=siz[to]; if(siz[to]>maxson) son[u]=to,maxson=siz[to]; } } void dfs2(int u,int topf){ invdfn[id[u]]=u; top[u]=topf; if(!son[u]) return; dfs2(son[u],topf); for(auto to:e[u]){ if(to==son[u]||to==fa[u]) continue; dfs2(to,to); } } void up_link(int rt){ mx[rt]=max(mx[ls],mx[rs]); mi[rt]=min(mi[ls],mi[rs]); } void build(int rt,int l,int r){ if(l==r) { mi[rt]=mx[rt]=p[invdfn[l]]; return; } build(ls,l,mid);build(rs,mid+1,r); up_link(rt); } int query(int op,int ql,int qr,int rt=1,int l=1,int r=n){ if(ql<=l&&r<=qr){ if(op==1) return mx[rt]; else return mi[rt]; } int ans; if(op==1) ans=0; else ans=2e9; if(mid>=ql) { if(op==1) ans=max(ans,query(op,ql,qr,ls,l,mid)); else ans=min(ans,query(op,ql,qr,ls,l,mid)); } if(mid<qr) { if(op==1) ans=max(ans,query(op,ql,qr,rs,mid+1,r)); else ans=min(ans,query(op,ql,qr,rs,mid+1,r)); } up_link(rt); return ans; } void change(int ql,int qr,int k,int rt=1,int l=1,int r=n){ if(ql<=l&&r<=qr){ mx[rt]=mi[rt]=k; return; } if(ql<=mid) change(ql,qr,k,ls,l,mid); if(qr>mid) change(ql,qr,k,rs,mid+1,r); up_link(rt); } void change_path(int x,int y,int val){ while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]]) swap(x,y); change(id[top[x]],id[x],val); x=fa[top[x]]; } if(dep[x]>dep[y]) swap(x,y); change(id[x],id[y],val); } int qpath(int x,int y,int op){ int ans; //1 max, 0 min if(op==1) ans=0; else ans=2e9; while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]]) swap(x,y); if(op==1) ans=max(ans,query(op,id[top[x]],id[x])); else ans=min(ans,query(op,id[top[x]],id[x])); x=fa[top[x]]; } if(dep[x]>dep[y]) swap(x,y); if(op==1) ans=max(ans,query(op,id[x],id[y])); else ans=min(ans,query(op,id[x],id[y])); return ans; } struct seg_tree{ int mx_pos[N<<2],se_pos[N<<2],lca[N<<2]; pair<int,int>merge(int a,int b,int c,int d){ int mx=-1,mxpos=-1; int w[5]={0}; w[1]=a;w[2]=b;w[3]=c;w[4]=d; for(int i=1;i<=4;i++){ if(w[i]==-1) continue; if(dep[w[i]]>mx){ mx=dep[w[i]]; mxpos=w[i]; } } int sepos=-1; for(int i=1;i<=4;i++){ if(w[i]==-1) continue; if(mxpos==w[i]) continue; if(LCA(mxpos,w[i])!=w[i]){ if(sepos==-1) { sepos=w[i]; } else if(dep[w[i]]>dep[sepos]){ sepos=w[i]; } } } return {mxpos,sepos}; } void up(int rt){ pair<int,int>out; out=merge(mx_pos[ls],se_pos[ls],mx_pos[rs],se_pos[rs]); mx_pos[rt]=out.first; se_pos[rt]=out.second; lca[rt]=LCA(lca[ls],lca[rs]); } void build(int rt=1,int l=1,int r=n){ if(l==r){ mx_pos[rt]=invp[l]; se_pos[rt]=-1; lca[rt]=invp[l]; return; } build(ls,l,mid);build(rs,mid+1,r); up(rt); } void update(int val,int pos,int rt=1,int l=1,int r=n){ if(l==r){ lca[rt]=pos; mx_pos[rt]=pos; se_pos[rt]=-1; return; } if(val<=mid) update(val,pos,ls,l,mid); else update(val,pos,rs,mid+1,r); up(rt); } pair<int,int> query(int ql,int qr,int rt=1,int l=1,int r=n){ if(ql<=l&&r<=qr) { pair<int,int>q; q.first=mx_pos[rt];q.second=se_pos[rt]; return q; } pair<int,int>lq,rq; lq={-1,-1};rq={-1,-1}; if(mid>=ql) lq=query(ql,qr,ls,l,mid); if(mid<qr) rq=query(ql,qr,rs,mid+1,r); return merge(lq.first,lq.second,rq.first,rq.second); } int qlca(int ql,int qr,int rt=1,int l=1,int r=n){ if(ql<=l&&r<=qr) { return lca[rt]; } int Llca=0,Rlca=0; if(mid>=ql) Llca=qlca(ql,qr,ls,l,mid); if(mid<qr) Rlca=qlca(ql,qr,rs,mid+1,r); if(Llca&&Rlca) return LCA(Llca,Rlca); else if(Llca) return Llca; else if(Rlca) return Rlca; } }t; void solve(){ cnt=0; cin>>n; for(int i=1;i<=n;i++) e[i].clear(),son[i]=0; for(int i=1;i<=n;i++) cin>>p[i],invp[p[i]]=i; for(int i=1;i<n;i++){ int x,y;cin>>x>>y; e[x].push_back(y); e[y].push_back(x); } dfs1(1,0); dfs2(1,1); build(1,1,n); for(int i = 1; i <= __lg(n); i++) for(int j = 1; j + (1 << i) - 1 <= n; j++) lcaf[j][i] = get(lcaf[j][i-1], lcaf[j + (1 << i - 1)][i-1]); t.build(); int m;cin>>m; while(m--){ int op;cin>>op; if(op==1) { int x,y;cin>>x>>y; int wx=p[x],wy=p[y]; change_path(x,x,wy),change_path(y,y,wx); t.update(wy,x),t.update(wx,y); p[x]=wy,p[y]=wx; } else { int l,r; cin>>l>>r; pair<int,int>tmp=t.query(l,r); int mx=tmp.first; int se=tmp.second; if(se==-1) se=t.qlca(l,r); int len_path=dep[mx]+dep[se]-2*dep[LCA(mx,se)]+1; if(qpath(mx,se,1)==r&&qpath(mx,se,0)==l&&r-l+1==len_path) cout<<"Yes"<<"\n"; else cout<<"No"<<"\n"; } } } signed main(){ ios_base::sync_with_stdio(false); cin.tie(0);cout.tie(0); int t;cin>>t; while(t--) solve(); return 0; }