Description

S国有N个城市,编号从1到N。城市间用N-1条双向道路连接,满足
从一个城市出发可以到达其它所有城市。每个城市信仰不同的宗教,如飞天面条神教、隐形独角兽教、绝地教都是常见的信仰。为了方便,我们用不同的正整数代表各种宗教,  S国的居民常常旅行。旅行时他们总会走最短路,并且为了避免麻烦,只在信仰和他们相同的城市留宿。当然旅程的终点也是信仰与他相同的城市。S国政府为每个城市标定了不同的旅行评级,旅行者们常会记下途中(包括起点和终点)留宿过的城市的评级总和或最大值。
在S国的历史上常会发生以下几种事件:
”CC x c”:城市x的居民全体改信了c教;
”CW x w”:城市x的评级调整为w;
”QS x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过的城市的评级总和;
”QM x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过
的城市的评级最大值。
由于年代久远,旅行者记下的数字已经遗失了,但记录开始之前每座城市的信仰与评级,还有事件记录本身是完好的。请根据这些信息,还原旅行者记下的数字。    为了方便,我们认为事件之间的间隔足够长,以致在任意一次旅行中,所有城市的评级和信仰保持不变。

Input

输入的第一行包含整数N,Q依次表示城市数和事件数。
接下来N行,第i+l行两个整数Wi,Ci依次表示记录开始之前,城市i的评级和信仰。
接下来N-1行每行两个整数x,y表示一条双向道路。
接下来Q行,每行一个操作,格式如上所述。

Output

对每个QS和QM事件,输出一行,表示旅行者记下的数字。

Sample Input

5 6
3 1
2 3
1 2
3 3
5 1
1 2
1 3
3 4
3 5
QS 1 5
CC 3 1
QS 1 5
CW 3 3
QS 1 5
QM 2 4

Sample Output

8
9
11
3

HINT

N,Q < =10^5,C < =10^5

数据保证对所有QS和QM事件,起点和终点城市的信仰相同;在任意时刻,城市的评级总是不大于10^4的正整数,且宗教值不大于C。

思路:
因为宗教数量只有10^,我们可以树链剖分完对于每一个宗教建立线段树
使用了类似于主席树的写法
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+;
const int M=1e7+;
int w[N],c[N],last[N*],s[],root[N];
int son[N],deep[N],dfn[N],top[N],fa[N][];
int mx[M],sum[M],ls[M],rs[M];
int n,q,cnt,tim,tot;
struct orz{
int v,next;}e[N*];
void add(int x,int y)
{
cnt++;
e[cnt].v=y;
e[cnt].next=last[x];
last[x]=cnt;
}
void dfs1(int x)
{
son[x]=;
for (int i=;i<=;i++)
{
if (s[i]<=deep[x]) fa[x][i]=fa[fa[x][i-]][i-];
else break;
}
for (int i=last[x];i;i=e[i].next)
{
int v=e[i].v;
if (v==fa[x][]) continue;
deep[v]=deep[x]+;
fa[v][]=x;
dfs1(v);
son[x]+=son[v];
}
}
void dfs2(int x,int chain)
{
tim++;
dfn[x]=tim;
top[x]=chain;
int k=;
for (int i=last[x];i;i=e[i].next)
{
if (deep[e[i].v]>deep[x] && son[e[i].v]>son[k])
k=e[i].v;
}
if (k) dfs2(k,chain);
for (int i=last[x];i;i=e[i].next)
{
if (deep[e[i].v]>deep[x] && e[i].v!=k)
dfs2(e[i].v,e[i].v);
}
}
int lca(int x,int y)
{
if (deep[x]<deep[y]) swap(x,y);
int t=deep[x]-deep[y];
for (int i=;i<=;i++)
if (s[i]&t) x=fa[x][i];
for (int i=;i>=;i--)
if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
if (x==y) return x;
return fa[x][];
}
//===========================================================
void PushUp(int s)
{
mx[s]=max(mx[ls[s]],mx[rs[s]]);
sum[s]=sum[ls[s]]+sum[rs[s]];
}
void change(int &s,int l,int r,int pos,int val)
{
if (!s) s=++tot;
if (l==r)
{
mx[s]=sum[s]=val;
return ;
}
int mid=(l+r)>>;
if (pos<=mid) change(ls[s],l,mid,pos,val);
else change(rs[s],mid+,r,pos,val);
PushUp(s);
}
int querysum(int s,int l,int r,int L,int R)
{
if (!s) return ;
if (L<=l&&r<=R) return sum[s];
int mid=(l+r)>>;
int ret=;
if (L<=mid) ret+=querysum(ls[s],l,mid,L,R);
if (R>mid) ret+=querysum(rs[s],mid+,r,L,R);
return ret;
}
int querymx(int s,int l,int r,int L,int R)
{
if (!s) return ;
if (L<=l&&r<=R) return mx[s];
int mid=(l+r)>>;
int ret=;
if (L<=mid) ret=max(ret,querymx(ls[s],l,mid,L,R));
if (R>mid) ret=max(ret,querymx(rs[s],mid+,r,L,R));
return ret;
}
//===========================================================
int solvesum(int c,int x,int y)
{
int ret=;
while (top[x]!=top[y]) //因为在这题中y是x的祖先所以不用考虑x和y的深度关系
{
ret+=querysum(root[c],,n,dfn[top[x]],dfn[x]);
x=fa[top[x]][];
}
ret+=querysum(root[c],,n,dfn[y],dfn[x]);
return ret;
}
int solvemx(int c,int x,int y)
{
int mx=;
while (top[x]!=top[y])
{
mx=max(mx,querymx(root[c],,n,dfn[top[x]],dfn[x]));
x=fa[top[x]][];
}
mx=max(mx,querymx(root[c],,n,dfn[y],dfn[x]));
return mx;
}
//===========================================================
void pre()
{
s[]=;
for (int i=;i<=;i++) s[i]=s[i-]*;
}
int main()
{
pre();
scanf("%d%d",&n,&q);
for (int i=;i<=n;i++)scanf("%d%d",&w[i],&c[i]);
int x,y;
for (int i=;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y); add(y,x);
}
dfs1(); dfs2(,); for (int i=;i<=n;i++)
change(root[c[i]],,n,dfn[i],w[i]); char op[];
while (q--)
{
scanf("%s",op);
scanf("%d%d",&x,&y);
if (op[]=='C')
{
if (op[]=='C')
{
change(root[c[x]],,n,dfn[x],);
c[x]=y;
change(root[c[x]],,n,dfn[x],w[x]);
}
else
{
change(root[c[x]],,n,dfn[x],y);
w[x]=y;
}
}
else
{
int f=lca(x,y);
if (op[]=='S')
{
int t=solvesum(c[x],x,f)+solvesum(c[x],y,f);g
if (c[x]==c[f]) t-=w[f];
printf("%d\n",t);
}
else
{
int t=max(solvemx(c[x],x,f),solvemx(c[x],y,f));
printf("%d\n",t);
}
}
}
return ;
}

ZOJ3531: [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. 关于UITableViewAutomaticDimension的产生的bug

      一.下面这句代码要想有作用 在iOS11之前需要适配,两个代理都需要实现 - (CGFloat)tableView:(UITableView *)tableView heightForHeader ...

  2. shell整数测试

  3. java中的成员变量、类变量,成员方法、类方法 属性和方法区别

    成员变量:包括实例变量和类变量,用static修饰的是类变量,不用static修饰的是实例变量,所有类的成员变量可以通过this来引用. 类变量:静态域,静态字段,或叫静态变量,它属于该类所有实例共有 ...

  4. css text文本

    CSS 文本格式 文本格式 This text is styled with some of the text formatting properties. The heading uses the ...

  5. POJ 1655 Balancing Act (树状dp入门)

    Description Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1...N. Deleting any nod ...

  6. 【Flutter学习】页面跳转之路由及导航

    一,概述 移动应用通常通过成为‘屏幕’或者‘页面’的全屏元素显示其内容,在Flutter中,这些元素统称为路由,它们由导航器Navigator组件管理.导航器管理一组路由Route对象,并提供了管理堆 ...

  7. Security基础(一):Linux基本防护措施、使用sudo分配管理权限、提高SSH服务安全

    一.Linux基本防护措施 目标: 本案例要求练习Linux系统的基本防护措施,完成以下任务: 修改用户zhangsan的账号属性,设置为2015-12-31日失效(禁止登录) 锁定用户lisi的账户 ...

  8. [NOIP模拟测试30]题解

    A.Return 出题人大概是怕自己的中文十级没人知道,所以写了这么一个***题面.可能又觉得这题太水怕全场A掉后自己面子过不去,于是又故意把输出格式说的含糊不清.(鬼知道"那么输出-1&q ...

  9. HTML5: HTML5 服务器发送事件(Server-Sent Events)

    ylbtech-HTML5: HTML5 服务器发送事件(Server-Sent Events) 1.返回顶部 1. HTML5 服务器发送事件(Server-Sent Events) HTML5 服 ...

  10. numpy 中文手册

    https://yiyibooks.cn/xx/NumPy_v111/user/index.html