您的位置:首页 > 其它

[bzoj 3531]sdoi2014 旅行

2015-06-22 08:04 375 查看
一眼树剖题

对每种颜色开一颗线段树,动态开点,记录最大值与和,查询直接查找,修改的话只会修改单点,所以最多增加2logn个节点

(原来把题目看错了,以为修改也是修改连续一段的,似乎这样空间会大很多)

#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int Maxn = 1000005;
int sum[Maxn*10], maxx[Maxn*10];
int Fa[Maxn], fa[Maxn];
int dep[Maxn], T[Maxn];
int size[Maxn], dfn[Maxn];
int L[Maxn], R[Maxn];
int w[Maxn], c[Maxn];
int son[Maxn*10][2];
int n,Q,x,y,id,tim;
char S[10];
vector <int> e[Maxn];

void find_heavy_edge(int x){
dep[x] = dep[fa[x]]+1;
int len = e[x].size();
size[x] = 1;
for (int i=0;i<len;i++)
if (e[x][i]!=fa[x]){
fa[e[x][i]] = x;
find_heavy_edge(e[x][i]);
size[x] += size[e[x][i]];
}
}

bool cmp(const int &a,const int &b)
{
return size[a] > size[b];
}

void link_heavy_edge(int x){
dfn[++tim] = x; L[x] = tim;
sort(e[x].begin(),e[x].end(),cmp);
if (x>1) e[x].erase( e[x].begin() );
else Fa[x] = x;
int len = e[x].size();
for (int i=0;i<len;i++)
{
if (i==0) Fa[e[x][i]] = Fa[x];
else Fa[e[x][i]] = e[x][i];
link_heavy_edge(e[x][i]);
}
R[x] = tim;
}

void insert(int &p,int l,int r,int pos,int data){
if (p==0) p = ++id;
if (l==r){
sum[p] = maxx[p] = data;
return;
}
int mid = (l+r)>>1;
if (mid>=pos) insert(son[p][0],l,mid,pos,data);
else insert(son[p][1],mid+1,r,pos,data);
sum[p] = sum[son[p][0]] + sum[son[p][1]];
maxx[p] = max( maxx[son[p][0]], maxx[son[p][1]] );
}

int query_sum(int p,int l,int r,int L,int R){
if (p==0) return 0;
if (L>r || l>R) return 0;
if (L<=l && R>=r) return sum[p];
int mid = (l+r)>>1;
return query_sum(son[p][0],l,mid,L,R) + query_sum(son[p][1],mid+1,r,L,R);
}

int query_max(int p,int l,int r,int L,int R){
if (p==0) return 0;
if (L>r || l>R) return 0;
if (L<=l && R>=r) return maxx[p];
int mid = (l+r)>>1;
return max( query_max(son[p][0],l,mid,L,R), query_max(son[p][1],mid+1,r,L,R) );
}

void work1(){
insert(T[c[x]],1,n,L[x],0);
c[x] = y;
insert(T[c[x]],1,n,L[x],w[x]);
}

void work2(){
w[x] = y;
insert(T[c[x]],1,n,L[x],w[x]);
}

void work3(){
int col = c[x], ans = 0;
while (Fa[x]!=Fa[y])
{
if (dep[Fa[x]]<dep[Fa[y]]) swap(x,y);
ans += query_sum(T[col],1,n,L[Fa[x]],L[x]);
x = fa[Fa[x]];
}
if (L[x]>L[y]) swap(x,y);
ans += query_sum(T[col],1,n,L[x],L[y]);
printf("%d\n",ans);
}

void work4(){
int col = c[x], ans = 0;
while (Fa[x]!=Fa[y])
{
if (dep[Fa[x]]<dep[Fa[y]]) swap(x,y);
ans = max(ans, query_max(T[col],1,n,L[Fa[x]],L[x]) );
x = fa[Fa[x]];
}
if (L[x]>L[y]) swap(x,y);
ans = max(ans, query_max(T[col],1,n,L[x],L[y]) );
printf("%d\n",ans);
}

int main(){
scanf("%d%d",&n,&Q);
for (int i=1;i<=n;i++)
scanf("%d%d",&w[i],&c[i]);
for (int i=1;i<n;i++){
scanf("%d%d",&x,&y);
e[x].push_back(y);
e[y].push_back(x);
}
find_heavy_edge(1);
link_heavy_edge(1);
for (int i=1;i<=n;i++)
insert(T[c[i]],1,n,L[i],w[i]);
while (Q--){
scanf("%s%d%d",S,&x,&y);
if (S[0]=='C' && S[1]=='C') work1();
if (S[0]=='C' && S[1]=='W') work2();
if (S[0]=='Q' && S[1]=='S') work3();
if (S[0]=='Q' && S[1]=='M') work4();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: