[破碎的状态] Vijos 1986
看起来就是个树链剖分的题...
https://vijos.org/p/1986
所以直接树链剖分剖一下就好了..
所以写的好长啊..
代码:
#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<string>
#include<time.h>
#include<math.h>
#include<memory>
#include<vector>
#include<bitset>
#include<fstream>
#include<stdio.h>
#include<utility>
#include<sstream>
#include<string.h>
#include<iostream>
#include<stdlib.h>
#include<algorithm>
using namespace std;
int a[100005];
struct edge
{
int y;
edge * next;
};
edge * li[100005];
edge * new_edge()
{
static edge a[200005];
static int top=0;
return &a[top++];
}
void inserts(int x,int y)
{
edge * t=new_edge();
t->y=y;
t->next=li[x];
li[x]=t;
}
void insert_edge(int x,int y)
{
inserts(x,y);
inserts(y,x);
}
edge * prefer[100005];
int dfn[100005];
int father[100005];
int size[100005];
int depth[100005];
int vis[100005];
void dfs1(int x)
{
size[x]=1;
edge * t;
int max_weight=0;
for (t=li[x];t!=0;t=t->next)
{
if (t->y==father[x]) continue;
father[t->y]=x;
depth[t->y]=depth[x]+1;
dfs1(t->y);
size[x]+=size[t->y];
if (size[t->y]>max_weight)
{
max_weight=size[t->y];
prefer[x]=t;
}
}
}
int up[100005];
void dfs2(int x)
{
static int num=0;
dfn[x]=num;
vis[num]=x;
num++;
if (prefer[x]==0) return;
up[prefer[x]->y]=up[x];
dfs2(prefer[x]->y);
edge * t;
for (t=li[x];t!=0;t=t->next)
{
if (t==prefer[x]) continue;
if (t->y==father[x]) continue;
up[t->y]=t->y;
dfs2(t->y);
}
}
int val[1<<18];
void build_tree(int num,int l,int r)
{
if (l==r-1)
{
val[num]=a[vis[l]];
return;
}
int mid=(l+r)/2;
build_tree(num*2+1,l,mid);
build_tree(num*2+2,mid,r);
val[num]=val[num*2+1]+val[num*2+2];
}
void change(int num,int l,int r,int k,int t)
{
if (l==r-1)
{
val[num]=t;
return;
}
int mid=(l+r)/2;
if (k<mid) change(num*2+1,l,mid,k,t);
else change(num*2+2,mid,r,k,t);
val[num]=val[num*2+1]+val[num*2+2];
}
int query(int num,int l,int r,int l0,int r0)
{
if ((l0<=l)&&(r<=r0))
{
return val[num];
}
int mid=(l+r)/2;
int sum=0;
if (l0<mid) sum+=query(num*2+1,l,mid,l0,r0);
if (mid<r0) sum+=query(num*2+2,mid,r,l0,r0);
return sum;
}
int main()
{
#ifdef absi2011
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
int n;
scanf("%d",&n);
int i;
for (i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
for (i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
x--;
y--;
insert_edge(x,y);
}
depth[0]=0;
father[0]=-1;
dfs1(0);
up[0]=0;
dfs2(0);
build_tree(0,0,n);
int m;
scanf("%d",&m);
for (i=0;i<m;i++)
{
static char oper[5];
scanf("%s",oper);
int x,y;
scanf("%d%d",&x,&y);
if (oper[0]=='C')
{
x--;
change(0,0,n,dfn[x],y);
}
else
{
x--;
y--;
int sum=0;
for (;;)
{
if (up[x]==up[y])
{
if (depth[x]<depth[y]) swap(x,y);
sum+=query(0,0,n,dfn[y],dfn[x]+1);
break;
}
else
{
if (depth[up[x]]<depth[up[y]]) swap(x,y);
sum+=query(0,0,n,dfn[up[x]],dfn[x]+1);
x=father[up[x]];
}
}
printf("%d\n",sum);
}
}
return 0;
}
评论 (0)