题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036
时间:
LCT(O((n+m) log n)):
树链剖分(O((n+m) log^2 n)):
代码(第一次尝试写轻重树链剖分,O(n log^2 n)的复杂度还可以。。下次再来写块状树,lct的代码链接(https://www.jianshu.com/p/6090162a7759 度娘一次不给贴太长的染色代码,只能代码另发一次了。。。)函数式线段树MLE了,空间O((n log n + q) log n)各种巨大啊 TAT):
(树链的太长贴不了染色的。。。)
#include
#include
#include
#include
using namespace std;
#define MAXN 30001
#define inf 0x7fffffff
#define MAXM 200001
#define clear(x) memset(x,0,sizeof(x))
struct edge{
int t;
edge *next;
edge (){
next=NULL;
}
}*he[MAXN];
int n,m,par[MAXN],Si[MAXN],Ch[MAXN],Que[MAXM][3],Index=0,Num=0,Id[MAXN],Arr[MAXN],Pos[MAXN],Fir[MAXN],Lca[MAXM],fat[MAXN],w[MAXN];
bool f[MAXN];
void AddEdge(int s,int t){edge *p=new(edge);p->t=t;p->next=he[s];he[s]=p;}
void Dfs_Si(int v){
f[v]=false;
Si[v]=1;
int maxSi=0;
for(edge *p=he[v];p;p=p->next){
if(f[p->t]){
par[p->t]=v;
Dfs_Si(p->t);
Si[v]+=Si[p->t];
if(Si[p->t]>maxSi){
maxSi=Si[p->t];
Ch[v]=p->t;
}
}
}
}
void Heavy_Edge(int v,bool flag){
if(flag) Fir[++Index]=v;
Id[v]=Index;
Arr[Pos[v]=++Num]=v;
f[v]=false;
if(Ch[v])Heavy_Edge(Ch[v],false);
for(edge *p=he[v];p;p=p->next){
if(f[p->t]&&p->t!=Ch[v]){
Heavy_Edge(p->t,true);
}
}
}
struct lca_type {
int t,r;
lca_type *next;
}*Fro[MAXN];
void Insert(int s,int t,int r){
lca_type *p=new(lca_type);
p->t=t;p->r=r;p->next=Fro[s];Fro[s]=p;
}
int Find(int v){
int i,j=v;
for(i=v;fat[i];i=fat[i]);
while(fat[j]){
int k=fat[j];
fat[j]=i;
j=k;
}
return i;
}
void Tarjan(int v){
f[v]=false;
for(lca_type *p=Fro[v];p;p=p->next)if(!f[p->t]) Lca[p->r]=Find(p->t);
for(edge *p=he[v];p;p=p->next)
if(f[p->t]){Tarjan(p->t);fat[Find(p->t)]=v;}
}
struct node{
int l,r,Max,Sum;
} T[MAXN*3];
void Build_SegT(int l,int r,int t){
T[t].l=l,T[t].r=r;
if(l==r){
T[t].Max=T[t].Sum=w[Arr[l]];
return;
}
Build_SegT(l,(l+r)>>1,t<<1);
Build_SegT(((l+r)>>1)+1,r,(t<<1)^1);
T[t].Max=max(T[t<<1].Max,T[(t<<1)^1].Max);
T[t].Sum=T[t<<1].Sum+T[(t<<1)^1].Sum;
}
void INIT(){
scanf("%d",&n);
memset(he,0,sizeof(he));
for(int i=0;i++>1))Change(v,u,t<<1)
; else Change(v,u,(t<<1)^1);
T[t].Sum=T[t<<1].Sum+T[(t<<1)^1].Sum;
T[t].Max=max(T[t<<1].Max,T[(t<<1)^1].Max);
}
int Max(int l,int r,int t){
if(T[t].l==l&&T[t].r==r)return T[t].Max;
int mid=(T[t].l+T[t].r)>>1;
if(r<=mid)return Max(l,r,t<<1);
if(l>mid)return Max(l,r,(t<<1)^1);
return max(Max(l,mid,t<<1),Max(mid+1,r,(t<<1)^1));
}
int Sum(int l,int r,int t){
if(T[t].l==l&&T[t].r==r)return T[t].Sum;
int mid=(T[t].l+T[t].r)>>1;
if(r<=mid)return Sum(l,r,t<<1);
if(l>mid)return Sum(l,r,(t<<1)^1);
return Sum(l,mid,t<<1)+Sum(mid+1,r,(t<<1)^1);
}
int GM(int v,int u){
int rec=-inf;
while(1){
if(Id[v]==Id[u])return max(rec,Max(Pos[u],Pos[v],1))
; else{rec=max(rec,Max(Pos[Fir[Id[v]]],Pos[v],1));v=par[Fir[Id[v]]];}
}
}
int GS(int v,int u){
int rec=0;
while(1){
if(Id[v]==Id[u])return rec+Sum(Pos[u],Pos[v],1); else rec+=Sum(Pos[Fir[Id[v]]],Pos[v],1),v=par[Fir[Id[v]]];
}
}
void Solve(){
for(int i=0;i++