这怕是noip的考试范围哦。Achen在半年前就会了的算法我现在都不会。
自己比较智障,连写3道题都是get_root()之后就去solve(z)而不是solve(root),搞得又T又RE
点分治模板(洛谷)
//Serene #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #include<set> using namespace std; #define ll long long #define db double #define For(i,a,b) for(int i=(a);i<=(b);++i) #define Rep(i,a,b) for(int i=(a);i>=(b);--i) const int maxn=1e4+7; int n,m,ans[maxn],p[maxn]; int size[maxn],son[maxn],sumsize,root,vis[maxn],len[maxn]; char cc; ll ff; template<typename T>void read(T& aa) { aa=0;cc=getchar();ff=1; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } int fir[maxn],nxt[2*maxn],to[2*maxn],v[2*maxn],e=0; void add(int x,int y,int z) { to[++e]=y;nxt[e]=fir[x];fir[x]=e;v[e]=z; to[++e]=x;nxt[e]=fir[y];fir[y]=e;v[e]=z; } void get_root(int pos,int f) { size[pos]=1; son[pos]=0; int y,z; for(y=fir[pos];y;y=nxt[y]) { if((z=to[y])==f||vis[z]) continue; get_root(z,pos); size[pos]+=size[z]; son[pos]=max(son[pos],size[z]); } son[pos]=max(son[pos],sumsize-size[pos]); if(son[pos]<son[root]) root=pos; } set<int> G; int zz[maxn],t; void get_ans(int x) { For(i,1,m) if(G.find(p[i]-x)!=G.end()) ans[i]|=1; } void dfs(int pos,int f) { int y,z; zz[++t]=len[pos]; get_ans(len[pos]); for(y=fir[pos];y;y=nxt[y]) { if(vis[z=to[y]]||z==f) continue; len[z]=len[pos]+v[y]; dfs(z,pos); } } void solve(int pos) { vis[pos]=1; G.clear(); G.insert(0); int y,z; for(y=fir[pos];y;y=nxt[y]) { if(vis[z=to[y]]) continue; len[z]=v[y]; dfs(z,pos); while(t) G.insert(zz[t--]); } for(y=fir[pos];y;y=nxt[y]) { if(vis[z=to[y]]) continue; sumsize=size[z]; root=0; get_root(z,0);solve(root); } } int main() { read(n); read(m); int x,y,z; For(i,1,n-1) { read(x); read(y); read(z); add(x,y,z); } For(i,1,m) read(p[i]); son[root=0]=sumsize=n; get_root(1,0); solve(root); For(i,1,m) printf(ans[i]? "AYE ":"NAY "); return 0; }
bzoj2152聪聪可可
//Serene #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; #define ll long long #define db double #define For(i,a,b) for(int i=(a);i<=(b);++i) #define Rep(i,a,b) for(int i=(a);i>=(b);--i) const int maxn=4e4+7; int n,root,vis[maxn],nowsum; char cc; ll ff; template<typename T>void read(T& aa) { aa=0;cc=getchar();ff=1; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } ll gcd(ll x,ll y) { return y==0? x:gcd(y,x%y); } int fir[maxn],nxt[2*maxn],to[2*maxn],e=0,v[2*maxn]; void add(int x,int y,int z) { to[++e]=y;nxt[e]=fir[x];fir[x]=e;v[e]=z%3; to[++e]=x;nxt[e]=fir[y];fir[y]=e;v[e]=z%3; } int son[maxn],size[maxn]; void get_root(int pos,int f) { size[pos]=1; son[pos]=0; int y,z; for(y=fir[pos];y;y=nxt[y]) { if((z=to[y])==f||vis[z]) continue; get_root(z,pos); size[pos]+=size[z]; if(size[z]>=son[pos]) son[pos]=size[z]; } son[pos]=max(son[pos],nowsum-size[pos]); if(son[pos]<son[root]) root=pos; } ll ans; ll now[10],tot[10],t; void dfs(int pos,int f,int x) { ++now[x]; int y,z; ans+=2*tot[(3-x)%3]; for(y=fir[pos];y;y=nxt[y]) { if(vis[z=to[y]]||z==f) continue; dfs(z,pos,(x+v[y])%3); } } void solve(int pos) { vis[pos]=1; int y,z; memset(tot,0,sizeof(tot)); tot[0]=1; for(y=fir[pos];y;y=nxt[y]) { if(vis[z=to[y]]) continue; dfs(z,pos,v[y]%3); For(i,0,2) tot[i]+=now[i],now[i]=0; } for(y=fir[pos];y;y=nxt[y]) { if(vis[z=to[y]]) continue; nowsum=size[z]; root=0; get_root(z,pos); solve(root); } } int main() { read(n); int x,y,z; ans=n; For(i,1,n-1) { read(x); read(y); read(z); add(x,y,z); } size[0]=son[0]=nowsum=n; get_root(1,0); solve(root); ll r=n*n;ll p=gcd(ans,r); ans/=p; r/=p; printf("%lld/%lld",ans,r); return 0; }
bzoj3648寝室管理
裸的点分治,环的处理就是直接把环跑一遍就可以了。
//Serene #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; #define ll long long #define db double #define For(i,a,b) for(int i=(a);i<=(b);++i) #define Rep(i,a,b) for(int i=(a);i>=(b);--i) const int maxn=1e5+7; int n,m,k,A,B,root,SUM; ll ans; char cc; ll ff; template<typename T>void read(T& aa) { aa=0;cc=getchar();ff=1; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } int f[maxn]; int find(int x){return x==f[x]? x:f[x]=find(f[x]);} int fir[maxn],nxt[2*maxn],to[2*maxn],e=0; void add(int x,int y) { to[++e]=y;nxt[e]=fir[x];fir[x]=e; to[++e]=x;nxt[e]=fir[y];fir[y]=e; } int sz[maxn]; void chge(int pos,int x) { while(pos<=n) { sz[pos]+=x; pos+=pos&-pos; } } int q(int pos) { ll rs=0; while(pos) { rs+=sz[pos]; pos-=pos&-pos; } return rs; } int size[maxn],U[maxn];bool vis[maxn]; void get_root(int pos,int f) { int y,z;U[pos]=0;size[pos]=1; for(y=fir[pos];y;y=nxt[y]) { if((z=to[y])==f||vis[z]) continue; get_root(z,pos); size[pos]+=size[z]; U[pos]=max(U[pos],size[z]); } U[pos]=max(U[pos],SUM-size[pos]); if(U[pos]<U[root]) root=pos; } int zz[maxn],s,t; void dfs(int pos,int f,int d,int dd) {//d:push dd:query zz[++t]=d; int y,z; ans+=(ll)q(n)-q(max(k-dd-1,0)); for(y=fir[pos];y;y=nxt[y]) { if((z=to[y])==f||vis[z]) continue; dfs(z,pos,d+1,dd+1); } } void solve(int pos) { vis[pos]=1; int y,z; zz[s=t=1]=1;chge(1,1); for(y=fir[pos];y;y=nxt[y]) { if(vis[z=to[y]]) continue; dfs(z,pos,2,1); For(i,s+1,t) chge(zz[i],1); s=t; } For(i,1,t) chge(zz[i],-1); for(y=fir[pos];y;y=nxt[y]) { if(vis[z=to[y]]) continue; SUM=size[z]; root=0; get_root(z,pos); solve(root); } } int h[maxn],tot; bool get_h(int pos,int f) { h[++tot]=pos; int y,z; if(pos==B) return vis[pos]=1; for(y=fir[pos];y;y=nxt[y]) { if((z=to[y])==f) continue; if(get_h(z,pos)) return vis[pos]=1; } tot--; return 0; } void get_ans() { memset(vis,0,sizeof(vis)); tot=0;s=t=0; get_h(A,0); For(r,1,tot) { dfs(h[r],0,r,tot-r+1); For(i,s+1,t) chge(zz[i],1); s=t; } } int main() { read(n); read(m); read(k); int x,y; For(i,1,n) f[i]=i; For(i,1,m) { read(x); read(y); if(find(x)==find(y)) A=x,B=y; else { f[find(x)]=find(y); add(x,y); } } U[0]=n+1; SUM=n; get_root(1,0); solve(root); if(n==m) get_ans(); printf("%lld",ans); return 0; } /* 5 5 2 1 3 2 4 3 5 4 1 5 2 */