洛谷P3313 [SDOI2014]旅行

来源:互联网 发布:淘宝化妆品店铺推荐 编辑:程序博客网 时间:2024/05/16 07:11

题目描述

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,并记下了途中留宿过的城市的评级最大值。

由于年代久远,旅行者记下的数字已经遗失了,但记录开始之前每座城市的信仰与评级,还有事件记录本身是完好的。请根据这些信息,还原旅行者记下的数字。 为了方便,我们认为事件之间的间隔足够长,以致在任意一次旅行中,所有城市的评级和信仰保持不变。

输入输出格式

输入格式:

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

输出格式:

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

输入输出样例

输入样例#1: 复制
5 63 12 31 23 35 11 21 33 43 5QS 1 5CC 3 1QS 1 5CW 3 3QS 1 5QM 2 4
输出样例#1: 复制
8    9    11    3

说明

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

数据保证对所有QS和QM事件,起点和终点城市的信仰相同;在任意时

刻,城市的评级总是不大于10^4的正整数,且宗教值不大于C。

一开始用了倍增LCA+主席树,然后完美地 TLE 了。。。

两天的百思不解后看了题解,发现要用 树链剖分+动态线段树。。。

于是花了一小时补一下 树剖 。。。

又调了一小时,终于AC了。。。

附上恶心的代码:

#include<iostream>#include<algorithm>#include<cstdio>#define MAXN 100010using namespace std;int n,m,d=1,e=1,g=1;int c[MAXN],w[MAXN],root[MAXN];int head[MAXN],id[MAXN],top[MAXN],deep[MAXN],fa[MAXN],son[MAXN],num[MAXN];struct node1{int next,to;}a[MAXN<<1];struct node2{int l,r,data1,data2;}b[MAXN*20];inline int read(){int date=0,w=1;char c=0;while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}return date*w;}inline int max(const int &x,const int &y){if(x>y)return x;return y;}void pushup(int rt){b[rt].data1=b[b[rt].l].data1+b[b[rt].r].data1;b[rt].data2=max(b[b[rt].l].data2,b[b[rt].r].data2);}void pushdown(int rt){b[rt].data1=b[rt].data2=b[rt].l=b[rt].r=0;}void insert(int k,int v,int l,int r,int &rt){int mid;if(!rt)rt=e++;if(l==v&&v==r){b[rt].data1=b[rt].data2=k;return;}mid=l+r>>1;if(v<=mid)insert(k,v,l,mid,b[rt].l);else insert(k,v,mid+1,r,b[rt].r);pushup(rt);}void remove(int k,int l,int r,int &rt){int mid;if(l==r){pushdown(rt);rt=0;return;}mid=l+r>>1;if(k<=mid)remove(k,l,mid,b[rt].l);else remove(k,mid+1,r,b[rt].r);pushup(rt);if(!b[rt].l&&!b[rt].r){pushdown(rt);rt=0;}}int query1(int s,int t,int l,int r,int rt){if(!rt)return 0;int mid;if(l==s&&r==t)return b[rt].data1;mid=l+r>>1;if(t<=mid)return query1(s,t,l,mid,b[rt].l);else if(s>mid)return query1(s,t,mid+1,r,b[rt].r);else return query1(s,mid,l,mid,b[rt].l)+query1(mid+1,t,mid+1,r,b[rt].r);}int query2(int s,int t,int l,int r,int rt){if(!rt)return 0;int mid;if(l==s&&r==t)return b[rt].data2;mid=l+r>>1;if(t<=mid)return query2(s,t,l,mid,b[rt].l);else if(s>mid)return query2(s,t,mid+1,r,b[rt].r);else return max(query2(s,mid,l,mid,b[rt].l),query2(mid+1,t,mid+1,r,b[rt].r));}void add(int x,int y){a[d].to=y;a[d].next=head[x];head[x]=d++;a[d].to=x;a[d].next=head[y];head[y]=d++;}void buildtree(int rt){int will;num[rt]=1;for(int i=head[rt];i;i=a[i].next){will=a[i].to;if(!deep[will]){deep[will]=deep[rt]+1;fa[will]=rt;buildtree(will);num[rt]+=num[will];if(num[will]>num[son[rt]])son[rt]=will;}}}void dfs(int rt,int fa){if(son[rt]){top[son[rt]]=top[rt];id[son[rt]]=++g;dfs(son[rt],rt);}int v;for(int i=head[rt];i;i=a[i].next){v=a[i].to;if(v==fa||v==son[rt])continue;top[v]=v;id[v]=++g;dfs(v,rt);}}void change1(int x,int y){remove(id[x],1,n,root[c[x]]);c[x]=y;insert(w[x],id[x],1,n,root[c[x]]);}void change2(int x,int y){w[x]=y;insert(w[x],id[x],1,n,root[c[x]]);}void work1(int x,int y){int cs=c[x],s=0;while(top[x]!=top[y]){if(deep[top[x]]<deep[top[y]])swap(x,y);s+=query1(id[top[x]],id[x],1,n,root[cs]);x=fa[top[x]];}if(deep[x]>deep[y])swap(x,y);s+=query1(id[x],id[y],1,n,root[cs]);printf("%d\n",s);}void work2(int x,int y){int cs=c[x],s=0;while(top[x]!=top[y]){if(deep[top[x]]<deep[top[y]])swap(x,y);s=max(s,query2(id[top[x]],id[x],1,n,root[cs]));x=fa[top[x]];}if(deep[x]>deep[y])swap(x,y);s=max(s,query2(id[x],id[y],1,n,root[cs]));printf("%d\n",s);}int main(){int x,y;char ch[3];n=read();m=read();for(int i=1;i<=n;i++){w[i]=read();c[i]=read();}for(int i=1;i<n;i++){x=read();y=read();add(x,y);}deep[1]=id[1]=top[1]=1;buildtree(1);dfs(1,0);for(int i=1;i<=n;i++)insert(w[i],id[i],1,n,root[c[i]]);while(m--){scanf("%s",ch);x=read();y=read();if(ch[0]=='C'){if(ch[1]=='C')change1(x,y);if(ch[1]=='W')change2(x,y);}if(ch[0]=='Q'){if(ch[1]=='S')work1(x,y);if(ch[1]=='M')work2(x,y);}}return 0;}

原创粉丝点击