对每一个宗教建一棵线段树,然后树剖搞搞

#include <iostream>
#include <cstdio>
using namespace std;
int n, m, w[100005], c[100005], uu, vv, hea[100005], cnt, dep[100005];
int fa[100005], top[100005], idx[100005], qaq, siz[100005], son[100005];
int rot[100005], orz, zdz[5000005], sum[5000005], lson[5000005];
int rson[5000005];
char ss[15];
struct Edge{
int too, nxt, val;
}edge[200005];
void add_edge(int fro, int too){
edge[++cnt].nxt = hea[fro];
edge[cnt].too = too;
hea[fro] = cnt;
}
void dfs1(int x, int f){
fa[x] = f;
siz[x] = 1;
dep[x] = dep[f] + 1;
int maxSon=-1;
for(int i=hea[x]; i; i=edge[i].nxt){
int t=edge[i].too;
if(t!=f){
dfs1(t, x);
siz[x] += siz[t];
if(maxSon<siz[t]) maxSon = siz[t], son[x] = t;
}
}
}
void dfs2(int x, int topf){
top[x] = topf;
idx[x] = ++qaq;
if(!son[x]) return ;
dfs2(son[x], topf);
for(int i=hea[x]; i; i=edge[i].nxt){
int t=edge[i].too;
if(t!=fa[x] && t!=son[x])
dfs2(t, t);
}
}
void pushUp(int o){
sum[o] = sum[lson[o]] + sum[rson[o]];
zdz[o] = max(zdz[lson[o]], zdz[rson[o]]);
}
void insert(int &o, int l, int r, int x, int w){
if(!o) o = ++orz;
if(l==r) sum[o] = zdz[o] = w;
else{
int mid=(l+r)>>1;
if(x<=mid) insert(lson[o], l, mid, x, w);
if(mid<x) insert(rson[o], mid+1, r, x, w);
pushUp(o);
}
}
void clr(int &o){
lson[o] = rson[o] = sum[o] = zdz[o] = 0;
o = 0;
}
void shanchu(int &o, int l, int r, int x){
if(l==r) clr(o);
else{
int mid=(l+r)>>1;
if(x<=mid) shanchu(lson[o], l, mid, x);
if(mid<x) shanchu(rson[o], mid+1, r, x);
pushUp(o);
if(lson[o]+rson[o]==0) clr(o);
}
}
int querySGTSum(int o, int l, int r, int x, int y){
if(!o) return 0;
if(l>=x && r<=y) return sum[o];
else{
int mid=(l+r)>>1;
int ans=0;
if(x<=mid) ans += querySGTSum(lson[o], l, mid, x, y);
if(mid<y) ans += querySGTSum(rson[o], mid+1, r, x, y);
return ans;
}
}
int querySGTMax(int o, int l, int r, int x, int y){
if(!o) return 0;
if(l>=x && r<=y) return zdz[o];
else{
int mid=(l+r)>>1;
int ans=0;
if(x<=mid) ans = max(ans, querySGTMax(lson[o], l, mid, x, y));
if(mid<y) ans = max(ans, querySGTMax(rson[o], mid+1, r, x, y));
return ans;
}
}
int querySum(int uu, int vv){
int bel=c[uu], ans=0;
while(top[uu]!=top[vv]){
if(dep[top[uu]]<dep[top[vv]]) swap(uu, vv);
ans += querySGTSum(rot[bel], 1, n, idx[top[uu]], idx[uu]);
uu = fa[top[uu]];
}
if(dep[uu]>dep[vv]) swap(uu, vv);
ans += querySGTSum(rot[bel], 1, n, idx[uu], idx[vv]);
return ans;
}
int queryMax(int uu, int vv){
int bel=c[uu], ans=0;
while(top[uu]!=top[vv]){
if(dep[top[uu]]<dep[top[vv]]) swap(uu, vv);
ans =max(ans, querySGTMax(rot[bel], 1, n, idx[top[uu]], idx[uu]));
uu = fa[top[uu]];
}
if(dep[uu]>dep[vv]) swap(uu, vv);
ans = max(ans, querySGTMax(rot[bel], 1, n, idx[uu], idx[vv]));
return ans;
}
int main(){
cin>>n>>m;
for(int i=1; i<=n; i++) scanf("%d %d", &w[i], &c[i]);
for(int i=1; i<n; i++){
scanf("%d %d", &uu, &vv);
add_edge(uu, vv);
add_edge(vv, uu);
}
dep[1] = 1;
dfs1(1, 0);
dfs2(1, 1);
for(int i=1; i<=n; i++)
insert(rot[c[i]], 1, n, idx[i], w[i]);
while(m--){
scanf("%s %d %d", ss, &uu, &vv);
if(ss[0]=='C' && ss[1]=='C'){
shanchu(rot[c[uu]], 1, n, idx[uu]);
c[uu] = vv;
insert(rot[c[uu]], 1, n, idx[uu], w[uu]);
}
if(ss[0]=='C' && ss[1]=='W'){
w[uu] = vv;
insert(rot[c[uu]], 1, n, idx[uu], w[uu]);
}
if(ss[0]=='Q' && ss[1]=='S')
printf("%d\n", querySum(uu, vv));
if(ss[0]=='Q' && ss[1]=='M')
printf("%d\n", queryMax(uu, vv));
}
return 0;
}

luogu3313 [SDOI2014]旅行的更多相关文章

  1. BZOJ 3531: [Sdoi2014]旅行 [树链剖分]

    3531: [Sdoi2014]旅行 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1685  Solved: 751[Submit][Status] ...

  2. 【BZOJ3531】[Sdoi2014]旅行 树链剖分+动态开点线段树

    [BZOJ3531][Sdoi2014]旅行 Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天 ...

  3. bzoj 3531 [Sdoi2014]旅行(树链剖分,线段树)

    3531: [Sdoi2014]旅行 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 876  Solved: 446[Submit][Status][ ...

  4. [SDOI2014]旅行

    洛谷 P3313 [SDOI2014]旅行 https://www.luogu.org/problem/show?pid=3313 题目描述 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接 ...

  5. B20J_3231_[SDOI2014]旅行_树链剖分+线段树

    B20J_3231_[SDOI2014]旅行_树链剖分+线段树 题意: S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,城市信仰不同的宗教,为了方便,我们用不同的正整数代表各种宗教. S国 ...

  6. [luogu P3313] [SDOI2014]旅行

    [luogu P3313] [SDOI2014]旅行 题目描述 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神 ...

  7. 洛谷 P3313 [SDOI2014]旅行 解题报告

    P3313 [SDOI2014]旅行 题目描述 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教 ...

  8. bzoj 3531 [Sdoi2014]旅行 (树剖+线段树 动态开点)

    3531: [Sdoi2014]旅行 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 2984  Solved: 1312[Submit][Status ...

  9. P3313 [SDOI2014]旅行

    P3313 [SDOI2014]旅行 树链剖分+动态线段树(并不是lct) 显然的,我们对于每一个宗教都要维护一个线段树. (那么空间不是爆炸了吗) 在这里引入:动态开点线段树 就是需要的点开起来,不 ...

随机推荐

  1. Codeforces 1107G(dp)

    1.答案要取连续的区间疯狂暗示线段树. 2.外层枚举r,内层枚举l显然过于暴力. 3.考虑内层的优化.dp[i]:以第i位为结尾的答案(长度大于1的).dp[i] = max(第一种情况,第二种情况) ...

  2. android 7.0 应用间文件共享FileProvider

    1.官方教程 Android 7.0 以后安全系数提高,应用间文件共享要使用FileProvider.原来的 file:/// Uri 替换为 content://Uri  https://devel ...

  3. [在读]webkit技术内幕

    看了一点点,还不适合目前的我看,搁置.

  4. 来,一起梳理下Android响应点击事件的方法

    一.设置setOnClickListener 这应该是最原始的方法了吧,来,先上代码: 布局文件: <Button android:id="@+id/button1" and ...

  5. 纯css滚动公告栏目

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  6. Linux下搭建DHCP服务器

    一.DHCP所需软件包 dhcp-common-4.1.1-34.Pl.el6.centos.x86_64 dhcp-4.1.1-34.pl.el6.centon.x86_64 二.编辑主配置文件 v ...

  7. Urlrewritefilte

    Urlrewritefilter是通过filter的形式,过滤所有的请求,然后再根据配置文件来转换成真正要访问的URL. 好处是隐藏真正的URL和美化提供给客户的URL. 比如,你的首页是www.** ...

  8. SDUT_2146:最小子序列和

    题目描述 给你一个长为n(10<=n<=10000)的数组,数组中的每一个数大于等于1小于等于1000000.请你找出一个长为k(1<=k<=1000)的子序列.找序列时,假如 ...

  9. gitlab利用ssh方式拉取代码

    问题1: Bad owner or permissions on .ssh/config的解决 当为本机配一个固定用户名远程登录某主机时,配置了一个config文件,但是在执行ssh免密码登录时报如下 ...

  10. vscode 打开新文件不替换旧文件

    设置 "workbench.editor.enablePreview": false