点分治
这怕是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\n":"NAY\n");
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
*/
弱者就是会被欺负呀

浙公网安备 33010602011771号