# 动态点分治

http://www.cnblogs.com/New-Godess/p/4420824.html

http://blog.csdn.net/liuguangzhe1999/article/details/51124781

http://blog.csdn.net/qq_34564984/article/details/53791362

http://blog.csdn.net/popoqqq/article/details/44489859

http://blog.csdn.net/popoqqq/article/details/44461423

http://www.cnblogs.com/iamqzh/p/5521172.html

http://www.cnblogs.com/wzj-is-a-juruo/p/4632699.html

http://hzwer.com/5247.html

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
typedef pair<int,int> pii;
typedef vector<int> vi;
#define fi first
#define se second
#define esb(x,e,b) (int e=fst[x],b=vb[e];e;e=nxt[e],b=vb[e])
#define SZ 666666
struct Heap
{
priority_queue<int> h,d;
int sz;
inline void cp_()
{
while(d.size()&&h.top()==d.top())
h.pop(), d.pop();
}
inline void push(int x) {h.push(x); ++sz;}
inline void del(int x) {d.push(x); --sz;}
inline int size() {return sz;}
inline int top()
{if(!sz) return 0; cp_(); return h.top();}
inline int s2(bool c=0)
{
if(!sz) return 0;
if(sz==1) return c?0:top();
int x=top(); h.pop();
int r=top(); h.push(x);
return x+r;
}
inline void pop() {cp_(); h.pop(); --sz;}
inline void op(int x,int o)
{if(!o) push(x); else del(x);}
}a,b[SZ],c[SZ];
Edg
int dep[SZ],fs[SZ],ed[SZ],S=0;
#define P 20
int minn[P][SZ],*ds=minn[0];
void dfs(int x,int f=0)
{
dep[x]=dep[f]+1;
ds[fs[x]=ed[x]=++S]=dep[x];
for esb(x,e,b)if(b!=f)
{
dfs(b,x);
ds[ed[x]=++S]=dep[x];
}
}
int l2[SZ];
void pre()
{
l2[0]=-1;
for(int i=1;i<=S;i++) l2[i]=l2[i>>1]+1;
for(int i=1;i<P;i++)
{
int*a=minn[i-1],*b=minn[i];
for(int j=1;j+(1<<i)-1<=S;j++)
b[j]=min(a[j],a[j+(1<<(i-1))]);
}
}
int dis(int a,int b)
{
if(fs[a]>fs[b]) swap(a,b);
int l=fs[a],r=ed[b],x=l2[r-l+1];
int mi=min(minn[x][l],minn[x][r-(1<<x)+1]);
return dep[a]+dep[b]-mi*2;
}
int dfa[SZ],sz[SZ],ms[SZ];
bool vis[SZ];
vi sons[SZ],tmp;
int root=0,sum;
void gr(int x,int f=0)
{
tmp.pb(x); sz[x]=1; ms[x]=0;
for esb(x,e,b)
{
if(b==f||vis[b]) continue;
gr(b,x); sz[x]+=sz[b];
ms[x]=max(ms[x],sz[b]);
}
ms[x]=max(ms[x],sum-sz[x]);
if(ms[x]<ms[root]||!root) root=x;
}
int n,col[SZ];
int dfz(int s=n,int bk=1,int df=0)
{
sum=s;root=0;tmp.clear();gr(bk);
int x=root;sons[x]=tmp;dfa[x]=df;
if(df)
{
for(int i=0;i<tmp.size();i++)
c[x].push(dis(tmp[i],df));
}
vis[x]=1;
for esb(x,e,g)
{
if(vis[g]) continue;
int r=dfz(sz[g],g,x);
b[x].push(c[r].top());
}
a.push(b[x].s2());
return x;
}
void flip(int x)
{
int ov2=b[x].s2(!col[x]),nv2=b[x].s2(col[x]);
if(ov2!=nv2) {a.del(ov2); a.push(nv2);}
for(int y=x;y;y=dfa[y])
{
int z=dfa[y],ov=c[y].top();
if(!z) continue;
c[y].op(dis(x,z),col[x]);
int nv=c[y].top();
if(nv==ov) continue;
int ov2=b[z].s2(col[z]);
if(ov) b[z].del(ov);
if(nv) b[z].push(nv);
int nv2=b[z].s2(col[z]);
if(ov2!=nv2)
{a.del(ov2); a.push(nv2);}
}
}
#define S myS
char ch,B[1<<15],*S=B,*T=B;
#define isd(c) (c>='0'&&c<='9')
int aa,bb;int F(){
while(ch=getc(),!isd(ch)&&ch!='-');ch=='-'?aa=bb=0:(aa=ch-'0',bb=1);
while(ch=getc(),isd(ch))aa=aa*10+ch-'0';return bb?aa:-aa;
}
#define gi F()
int main()
{
n=gi;
int tot=n;
for(int i=1;i<n;i++)
dfs(1); pre(); dfz();
int q=gi;
while(q--)
{
char s=getc();
if(s=='G')
{
if(tot) printf("%d\n",a.top());
else puts("-1");
continue;
}
int x=gi;
if(col[x]) ++tot; else --tot;
col[x]^=1; flip(x);
}
}

UPD：好像可以把复杂度改对，如果一个点有多个孩子，可以把孩子建成线段树那样，强制把每个点变成不超过两个孩子，这样走复杂度听说就对了。

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
typedef pair<int,int> pii;
typedef vector<int> vi;
#define fi first
#define se second
#define esb(x,e,b) (int e=fst[x],b=vb[e];e;e=nxt[e],b=vb[e])
#define SZ 666666
Edg
int dep[SZ],fs[SZ],ed[SZ],S=0;
#define P 20
int minn[P][SZ],*ds=minn[0];
void dfs(int x,int f=0)
{
dep[x]=dep[f]+1;
ds[fs[x]=ed[x]=++S]=dep[x];
for esb(x,e,b)if(b!=f)
{
dfs(b,x);
ds[ed[x]=++S]=dep[x];
}
}
int l2[SZ];
void pre()
{
l2[0]=-1;
for(int i=1;i<=S;i++) l2[i]=l2[i>>1]+1;
for(int i=1;i<P;i++)
{
int*a=minn[i-1],*b=minn[i];
for(int j=1;j+(1<<i)-1<=S;j++)
b[j]=min(a[j],a[j+(1<<(i-1))]);
}
}
int dis(int a,int b)
{
if(fs[a]>fs[b]) swap(a,b);
int l=fs[a],r=ed[b],x=l2[r-l+1];
int mi=min(minn[x][l],minn[x][r-(1<<x)+1]);
return dep[a]+dep[b]-mi*2;
}
int dfa[SZ],sz[SZ],ms[SZ],cmpd[SZ];
bool vis[SZ];
vi sons[SZ],pos[SZ],bt[SZ],tmp;
vi sons2[SZ],pos2[SZ],bt2[SZ];
int query(vi& v,int x)
{
int ans=0;
for(++x;x;x-=x&-x) ans+=v[x-1];
return ans;
}
void edt(vi& v,int x,int y)
{
for(++x;x<=v.size();x+=x&-x) v[x-1]+=y;
}
int bs(vi& v,int g)
{
return
min(int(upper_bound(v.begin(),v.end(),g)-v.begin()-1),
(int)v.size()-1);
}
int root=0,sum;
void gr(int x,int f=0)
{
tmp.pb(x); sz[x]=1; ms[x]=0;
for esb(x,e,b)
{
if(b==f||vis[b]) continue;
gr(b,x); sz[x]+=sz[b];
ms[x]=max(ms[x],sz[b]);
}
ms[x]=max(ms[x],sum-sz[x]);
if(ms[x]<ms[root]||!root) root=x;
}
bool cmp(int a,int b) {return cmpd[a]<cmpd[b];}
int n,m,val[SZ];
void dfz(int s=n,int bk=1,int df=0)
{
sum=s;root=0;tmp.clear();gr(bk);
int x=root;sons[x]=tmp;dfa[x]=df;
for(int i=0;i<tmp.size();i++)
cmpd[tmp[i]]=dis(tmp[i],x);
sort(sons[x].begin(),sons[x].end(),cmp);
bt[x].resize(tmp.size());
for(int i=0;i<tmp.size();i++)
pos[sons[x][i]].pb(i),
edt(bt[x],i,val[sons[x][i]]);
for(int i=0;i<tmp.size();i++)
sons[x][i]=cmpd[sons[x][i]];
//前方高能
if(df)
{
sons2[x]=tmp;
for(int i=0;i<tmp.size();i++)
cmpd[tmp[i]]=dis(tmp[i],df);
sort(sons2[x].begin(),sons2[x].end(),cmp);
bt2[x].resize(tmp.size());
for(int i=0;i<tmp.size();i++)
pos2[sons2[x][i]].pb(i),
edt(bt2[x],i,val[sons2[x][i]]);
for(int i=0;i<tmp.size();i++)
sons2[x][i]=cmpd[sons2[x][i]];
}
vis[x]=1;
for esb(x,e,g)
if(!vis[g]) dfz(sz[g],g,x);
}
void upd(int x,int dv)
{
for(int y=x,*z=&pos[x][pos[x].size()-1]
,*z2=&pos2[x][pos2[x].size()-1];y;
y=dfa[y],--z,--z2)
{
edt(bt[y],*z,dv);
if(dfa[y]) edt(bt2[y],*z2,dv);
}
}
int qd(int x,int k)
{
int ans=0;
for(int y=x,bk=0;y;bk=y,y=dfa[y])
{
int d=k-dis(x,y),
ca=query(bt[y],bs(sons[y],d));
if(bk) ca-=query(bt2[bk],bs(sons2[bk],d));
ans+=ca;
}
return ans;
}
#define S myS
char ch,B[1<<15],*S=B,*T=B;
#define isd(c) (c>='0'&&c<='9')
int aa,bb;int F(){
while(ch=getc(),!isd(ch)&&ch!='-');ch=='-'?aa=bb=0:(aa=ch-'0',bb=1);
while(ch=getc(),isd(ch))aa=aa*10+ch-'0';return bb?aa:-aa;
}
#define gi F()
int main()
{
n=gi,m=gi;
for(int i=1;i<=n;i++) val[i]=gi;
for(int i=1;i<n;i++)
dfs(1); pre(); dfz();
int lans=0;
while(m--)
{
int a=gi,b=gi^lans,c=gi^lans;
if(!a)
{
printf("%d\n",lans=qd(b,c));
continue;
}
upd(b,c-val[b]); val[b]=c;
}
}

posted @ 2017-02-13 11:22 fjzzq2002 阅读(...) 评论(...) 编辑 收藏