这里主要是我的动态点分治的练习记录。
动态点分治就是可以修改信息的点分治。在机房里面观战学长互怼对方“XXX为什么那么假?” 以及大神zjt学长:“点分治是什么?不会啊” 23333333。
T1 bzoj1095 动态点分治+堆
常数上天了!
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
const int N=100005;
int n,m,u,v,cnt,idx,head[N],to[N*2],nxt[N*2],dep[N],dfn[N],siz[N],Log2[N*2],pos[N*2],f[N*2][20];
int rt,mi,size,fa[N];
bool vis[N],ck[N];
char *p,s[10],ch[20000005];
inline int rd(){
register int ret=0;
while(*p<'0'||*p>'9'){
p++;
}
while(*p>='0'&&*p<='9'){
ret=ret*10+*p-'0';
p++;
}
return ret;
}
void adde(int u,int v){
to[++cnt]=v;
nxt[cnt]=head[u];
head[u]=cnt;
}
void dfs(int pre,int u){
dfn[u]=++idx;
pos[idx]=u;
siz[u]=1;
int v;
for(int i=head[u];i;i=nxt[i]){
v=to[i];
if(v!=pre){
dep[v]=dep[u]+1;
dfs(u,v);
pos[++idx]=u;
siz[u]+=siz[v];
}
}
}
void st(){
for(int i=1;i<=idx;i++){
f[i][0]=pos[i];
}
for(int j=1;j<=20;j++){
for(int i=1;i+(1<<j)-1<=idx;i++){
if(dep[f[i][j-1]]<dep[f[i+(1<<(j-1))][j-1]]){
f[i][j]=f[i][j-1];
}else{
f[i][j]=f[i+(1<<(j-1))][j-1];
}
}
}
}
int lca(int u,int v){
if(dfn[v]<dfn[u]){
swap(u,v);
}
int k=Log2[dfn[v]-dfn[u]];
if(dep[f[dfn[u]][k]]<dep[f[dfn[v]-(1<<k)+1][k]]){
return f[dfn[u]][k];
}else{
return f[dfn[v]-(1<<k)+1][k];
}
}
int dis(int u,int v){
return dep[u]+dep[v]-2*dep[lca(u,v)];
}
void dfsroot(int pre,int u){
siz[u]=1;
int v,mx=0;
for(int i=head[u];i;i=nxt[i]){
v=to[i];
if(v!=pre&&!vis[v]){
dfsroot(u,v);
siz[u]+=siz[v];
mx=max(mx,siz[v]);
}
}
mx=max(mx,size-siz[u]);
if(mx<mi){
rt=u;
mi=mx;
}
}
void dfstree(int pre,int u){
vis[u]=true;
fa[u]=pre;
int v;
for(int i=head[u];i;i=nxt[i]){
v=to[i];
if(!vis[v]){
mi=size=siz[v];
dfsroot(u,v);
dfstree(u,rt);
}
}
}
struct heap{
priority_queue<int> A,B;
void push(int x){
A.push(x);
}
void remove(int x){
B.push(x);
}
void pop(){
while(B.size()&&A.top()==B.top()){
A.pop();
B.pop();
}
if(A.size()){
A.pop();
}
}
int top(){
while(B.size()&&A.top()==B.top()){
A.pop();
B.pop();
}
return A.size()?A.top():0;
}
int size(){
return A.size()-B.size();
}
int sectop(){
if(size()<2){
return 0;
}
int x=top();
pop();
int y=top();
push(x);
return y;
}
}A,B[N],C[N];
void insert(int x){
if(B[x].size()>=2){
A.push(B[x].top()+B[x].sectop());
}
}
void remove(int x){
if(B[x].size()>=2){
A.remove(B[x].top()+B[x].sectop());
}
}
void off(int u){
remove(u);
B[u].push(0);
insert(u);
for(int i=u;fa[i];i=fa[i]){
remove(fa[i]);
if(C[i].size()){
B[fa[i]].remove(C[i].top());
}
C[i].push(dis(fa[i],u));
if(C[i].size()){
B[fa[i]].push(C[i].top());
}
insert(fa[i]);
}
}
void on(int u){
remove(u);
B[u].remove(0);
insert(u);
for(int i=u;fa[i];i=fa[i]){
remove(fa[i]);
if(C[i].size()){
B[fa[i]].remove(C[i].top());
}
C[i].remove(dis(fa[i],u));
if(C[i].size()){
B[fa[i]].push(C[i].top());
}
insert(fa[i]);
}
}
int main(){
fread(ch,20000000,1,stdin);
p=ch;
for(int i=2;i<=200000;i++){
Log2[i]=Log2[i/2]+1;
}
n=rd();
for(int i=1;i<n;i++){
u=rd(),v=rd();
adde(u,v);
adde(v,u);
}
dfs(0,1);
st();
mi=size=siz[1];
dfsroot(0,1);
dfstree(0,rt);
for(int i=1;i<=n;i++){
for(int j=i;fa[j];j=fa[j]){
C[j].push(dis(fa[j],i));
}
}
for(int i=1;i<=n;i++){
if(fa[i]){
B[fa[i]].push(C[i].top());
}
}
for(int i=1;i<=n;i++){
B[i].push(0);
ck[i]=false;
insert(i);
}
cnt=n;
m=rd();
for(int i=1;i<=m;i++){
s[0]=*p;
p++;
while(s[0]!='G'&&s[0]!='C'){
s[0]=*p;
p++;
}
if(s[0]=='G'){
if(cnt<=1){
printf("%d
",cnt-1);
}else{
printf("%d
",A.top());
}
}else{
u=rd();
if(!ck[u]){
if(i==3){
u++;
u--;
}
on(u);
cnt--;
ck[u]=true;
}else{
off(u);
cnt++;
ck[u]=false;
}
}
}
return 0;
}
T2 bzoj3730 动态树分治+线段树乱搞
RE得要死==
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=200005;
int n,m,op,u,v,cnt,idx,tot,ans,Log2[N*2],a[N],head[N],to[N*2],nxt[N*2],dfn[N],dep[N],siz[N],pos[N*2],f[N*2][25];
int rt,mi,size,fa[N],root[N][2],sumv[N*50],ch[N*50][2],dd[N];
bool vis[N];
void adde(int u,int v){
to[++cnt]=v;
nxt[cnt]=head[u];
head[u]=cnt;
}
void dfs(int pre,int u){
dfn[u]=++idx;
pos[idx]=u;
siz[u]=1;
int v;
for(int i=head[u];i;i=nxt[i]){
v=to[i];
if(v!=pre){
dep[v]=dep[u]+1;
dfs(u,v);
siz[u]+=siz[v];
pos[++idx]=u;
}
}
}
void st(){
for(int i=1;i<=idx;i++){
f[i][0]=pos[i];
}
for(int j=1;j<=20;j++){
for(int i=1;i+(1<<j)-1<=idx;i++){
if(dep[f[i][j-1]]<dep[f[i+(1<<(j-1))][j-1]]){
f[i][j]=f[i][j-1];
}else{
f[i][j]=f[i+(1<<(j-1))][j-1];
}
}
}
}
int lca(int u,int v){
if(dfn[u]>dfn[v]){
swap(u,v);
}
int k=Log2[dfn[v]-dfn[u]];
if(dep[f[dfn[u]][k]]<dep[f[dfn[v]-(1<<k)+1][k]]){
return f[dfn[u]][k];
}else{
return f[dfn[v]-(1<<k)+1][k];
}
}
int dis(int u,int v){
return dep[u]+dep[v]-2*dep[lca(u,v)];
}
void upd(int &o,int l,int r,int k,int v){
if(!o){
o=++tot;
}
sumv[o]+=v;
if(l==r){
return;
}
int mid=(l+r)/2;
if(k<=mid){
upd(ch[o][0],l,mid,k,v);
}else{
upd(ch[o][1],mid+1,r,k,v);
}
}
int qry(int o,int l,int r,int L,int R){
if(!o){
return 0;
}
if(L<=l&&R>=r){
return sumv[o];
}
int mid=(l+r)/2,ans=0;
if(L<=mid){
ans+=qry(ch[o][0],l,mid,L,R);
}if(R>mid){
ans+=qry(ch[o][1],mid+1,r,L,R);
}
return ans;
}
void dfsroot(int pre,int u){
siz[u]=1;
int v,mx=0;
for(int i=head[u];i;i=nxt[i]){
v=to[i];
if(!vis[v]&&v!=pre){
dfsroot(u,v);
siz[u]+=siz[v];
mx=max(mx,siz[v]);
}
}
mx=max(mx,size-siz[u]);
if(mx<mi){
rt=u;
mi=mx;
}
}
void init(int rt,int md,int pre,int u){
upd(root[rt][md],0,n,dd[u],a[u]);
int v;
for(int i=head[u];i;i=nxt[i]){
v=to[i];
if(!vis[v]&&v!=pre){
dd[v]=dd[u]+1;
init(rt,md,u,v);
}
}
}
void dfstree(int u){
vis[u]=true;
int v;
dd[u]=0;
init(u,0,0,u);
for(int i=head[u];i;i=nxt[i]){
v=to[i];
if(!vis[v]){
mi=size=siz[v];
dd[v]=1;
dfsroot(u,v);
init(rt,1,u,v);
fa[rt]=u;
dfstree(rt);
}
}
}
int query(int u,int d){
int ans=qry(root[u][0],0,n,0,d),tmp;
for(int i=u;fa[i];i=fa[i]){
tmp=dis(fa[i],u);
ans+=qry(root[fa[i]][0],0,n,0,d-tmp)-qry(root[i][1],0,n,0,d-tmp);
}
return ans;
}
void update(int u,int k){
int tmp;
upd(root[u][0],0,n,0,k-a[u]);
for(int i=u;fa[i];i=fa[i]){
tmp=dis(fa[i],u);
upd(root[fa[i]][0],0,n,tmp,k-a[u]);
upd(root[i][1],0,n,tmp,k-a[u]);
}
a[u]=k;
}
int main(){
for(int i=2;i<=200000;i++){
Log2[i]=Log2[i/2]+1;
}
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<n;i++){
scanf("%d%d",&u,&v);
adde(u,v);
adde(v,u);
}
dfs(0,1);
st();
size=mi=siz[1];
dfsroot(0,1);
dfstree(rt);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&op,&u,&v);
u^=ans;
v^=ans;
if(op==0){
printf("%d
",ans=query(u,v));
}else{
update(u,v);
}
}
return 0;
}
T3 bzoj4372 动态树分治+线段树
RMQ求lca居然打错==
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100005;
int n,m,u,v,d,cnt,head[N],to[N*2],nxt[N*2];
int idx,lg2[N*2],dfn[N],dep[N],siz[N],pos[N*2],f[N*2][20];
int mi,size,rt,fa[N];
int tot,root[N][2],tag[20000005],ch[20000005][2];
bool vis[N];
char s[5];
void adde(int u,int v){
to[++cnt]=v;
nxt[cnt]=head[u];
head[u]=cnt;
}
void dfs(int pre,int u){
dfn[u]=++idx;
pos[idx]=u;
int v;
for(int i=head[u];i;i=nxt[i]){
v=to[i];
if(v!=pre){
dep[v]=dep[u]+1;
dfs(u,v);
pos[++idx]=u;
}
}
}
void st(){
for(int i=1;i<=idx;i++){
f[i][0]=pos[i];
}
for(int j=1;j<=20;j++){
for(int i=1;i+(1<<j)-1<=idx;i++){
if(dep[f[i][j-1]]<dep[f[i+(1<<(j-1))][j-1]]){
f[i][j]=f[i][j-1];
}else{
f[i][j]=f[i+(1<<(j-1))][j-1];
}
}
}
}
int lca(int u,int v){
if(dfn[u]>dfn[v]){
swap(u,v);
}
int k=lg2[dfn[v]-dfn[u]];
if(dep[f[dfn[u]][k]]<dep[f[dfn[v]-(1<<k)+1][k]]){
return f[dfn[u]][k];
}else{
return f[dfn[v]-(1<<k)+1][k];
}
}
void dfsroot(int pre,int u){
siz[u]=1;
int v,mx=0;
for(int i=head[u];i;i=nxt[i]){
v=to[i];
if(v!=pre&&!vis[v]){
dfsroot(u,v);
siz[u]+=siz[v];
mx=max(mx,siz[v]);
}
}
mx=max(mx,size-siz[u]);
if(mx<mi){
mi=mx;
rt=u;
}
}
int dis(int u,int v){
return dep[u]+dep[v]-2*dep[lca(u,v)];
}
void build(int pre,int u){
vis[u]=true;
fa[u]=pre;
int v;
for(int i=head[u];i;i=nxt[i]){
v=to[i];
if(!vis[v]){
mi=size=siz[v];
dfsroot(u,v);
build(u,rt);
}
}
}
void upd(int &o,int l,int r,int L,int R,int v){
if(!o){
o=++tot;
}
if(L==l&&R==r){
tag[o]+=v;
return;
}
int mid=(l+r)/2;
if(R<=mid){
upd(ch[o][0],l,mid,L,R,v);
}else if(L>mid){
upd(ch[o][1],mid+1,r,L,R,v);
}else{
upd(ch[o][0],l,mid,L,mid,v);
upd(ch[o][1],mid+1,r,mid+1,R,v);
}
}
int qry(int o,int l,int r,int k){
if(!o){
return 0;
}
if(l==r){
return tag[o];
}
int mid=(l+r)/2;
if(k<=mid){
return tag[o]+qry(ch[o][0],l,mid,k);
}{
return tag[o]+qry(ch[o][1],mid+1,r,k);
}
}
int query(int u){
int ret=qry(root[u][0],0,n,0),tmp;
for(int i=u;fa[i];i=fa[i]){
tmp=dis(fa[i],u);
ret+=qry(root[fa[i]][0],0,n,tmp)-qry(root[i][1],0,n,tmp);
}
return ret;
}
void update(int u,int d,int w){
upd(root[u][0],0,n,0,d,w);
int tmp;
for(int i=u;fa[i];i=fa[i]){
tmp=dis(fa[i],u);
if(tmp>d){
continue;
}
upd(root[fa[i]][0],0,n,0,d-tmp,w);
upd(root[i][1],0,n,0,d-tmp,w);
}
}
int main(){
for(int i=2;i<=200000;i++){
lg2[i]=lg2[i/2]+1;
}
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++){
scanf("%d%d",&u,&v);
adde(u,v);
adde(v,u);
}
dfs(0,1);
st();
mi=size=n;
dfsroot(0,1);
build(0,rt);
for(int i=1;i<=m;i++){
scanf("%s%d",s,&u);
if(s[0]=='Q'){
printf("%d
",query(u));
}else{
scanf("%d%d",&d,&v);
update(u,d,v);
}
}
return 0;
}
T4 bzoj4012
在二分那里卡了好久,一气之下手打二分。(silly STL!) 一对比,树剖+主席树真的是太优越了!
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=150005;
int n,m,u,v,d,l,r,mod,cnt,a[N],head[N],to[N*2],nxt[N*2],dd[N*2];
int idx,dep[N],dfn[N*2],pos[N*2],f[N*2][20],Log2[N*2];
int mi,size,rt,siz[N],fa[N];
ll ans,dis[N];
bool vis[N];
struct data{
int col;
ll d,sum;
bool operator < (const data &a) const{
return col==a.col?d<a.d:col<a.col;
}
};
vector<data> V[2][N];
void adde(int u,int v,int d){
to[++cnt]=v;
nxt[cnt]=head[u];
dd[cnt]=d;
head[u]=cnt;
}
void dfs(int pre,int u){
dfn[u]=++idx;
pos[idx]=u;
siz[u]=1;
int v;
for(int i=head[u];i;i=nxt[i]){
v=to[i];
if(v!=pre){
dep[v]=dep[u]+1;
dis[v]=dis[u]+dd[i];
dfs(u,v);
pos[++idx]=u;
siz[u]+=siz[v];
}
}
}
void st(){
for(int i=1;i<=idx;i++){
f[i][0]=pos[i];
}
for(int j=1;j<=20;j++){
for(int i=1;i+(1<<j)-1<=idx;i++){
if(dep[f[i][j-1]]<dep[f[i+(1<<(j-1))][j-1]]){
f[i][j]=f[i][j-1];
}else{
f[i][j]=f[i+(1<<(j-1))][j-1];
}
}
}
}
int lca(int u,int v){
if(dfn[v]<dfn[u]){
swap(u,v);
}
int k=Log2[dfn[v]-dfn[u]];
if(f[dfn[u]][k]<f[dfn[v]-(1<<k)+1][k]){
return f[dfn[u]][k];
}else{
return f[dfn[v]-(1<<k)+1][k];
}
}
ll dist(int u,int v){
return dis[u]+dis[v]-2*dis[lca(u,v)];
}
void dfsroot(int pre,int u){
siz[u]=1;
int v,mx=0;
for(int i=head[u];i;i=nxt[i]){
v=to[i];
if(!vis[v]&&v!=pre){
dfsroot(u,v);
siz[u]+=siz[v];
mx=max(mx,siz[v]);
}
}
mx=max(mx,size-siz[u]);
if(mx<mi){
mi=mx;
rt=u;
}
}
void update(int rt,int pre,int u,int dis,int md){
V[md][rt].push_back((data){a[u],dis,0});
int v;
for(int i=head[u];i;i=nxt[i]){
v=to[i];
if(!vis[v]&&v!=pre){
update(rt,u,v,dis+dd[i],md);
}
}
}
void build(int pre,int u){
vis[u]=true;
fa[u]=pre;
update(u,0,u,0,0);
int v;
for(int i=head[u];i;i=nxt[i]){
v=to[i];
if(!vis[v]){
mi=size=siz[v];
dfsroot(u,v);
update(rt,u,v,dd[i],1);
build(u,rt);
}
}
}
int find(vector<data> &a,data x){
int l=0,r=a.size()-1,mid;
while(l<r){
mid=(l+r+1)/2;
if(a[mid]<x){
l=mid;
}else{
r=mid-1;
}
}
return l;
}
ll query(int u,int l,int r){
int L=find(V[0][u],(data){l,-1,0}),R=find(V[0][u],(data){r,(ll)1e18,0});
ll ans=V[0][u][R].sum-V[0][u][L].sum,d;
for(int i=u;fa[i];i=fa[i]){
d=dist(fa[i],u);
L=find(V[0][fa[i]],(data){l,-1,0}),R=find(V[0][fa[i]],(data){r,(ll)1e18,0});
ans+=V[0][fa[i]][R].sum-V[0][fa[i]][L].sum+d*(R-L);
L=find(V[1][i],(data){l,-1,0}),R=find(V[1][i],(data){r,(ll)1e18,0});
ans-=V[1][i][R].sum-V[1][i][L].sum+d*(R-L);
}
return ans;
}
int main(){
for(int i=2;i<=300000;i++){
Log2[i]=Log2[i/2]+1;
}
scanf("%d%d%d",&n,&m,&mod);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<n;i++){
scanf("%d%d%d",&u,&v,&d);
adde(u,v,d);
adde(v,u,d);
}
dfs(0,1);
st();
mi=size=n;
dfsroot(0,1);
build(0,rt);
for(int i=1;i<=n;i++){
for(int j=0;j<=1;j++){
V[j][i].push_back((data){-1,0,0});
sort(V[j][i].begin(),V[j][i].end());
if(V[j][i].size()){
V[j][i][0].sum=V[j][i][0].d;
}
for(int k=1;k<V[j][i].size();k++){
V[j][i][k].sum=V[j][i][k-1].sum+V[j][i][k].d;
}
}
}
while(m--){
scanf("%d%d%d",&u,&l,&r);
l=(l+ans)%mod;
r=(r+ans)%mod;
if(l>r){
swap(l,r);
}
printf("%lld
",ans=query(u,l,r));
}
return 0;
}