LOJ2195 旅行

LOJ2195 旅行

题目描述
S 国有 N 个城市,编号从 1 到 N。城市间用 N-1 条双向道路连接,满足从一个城市出发可以到达其它所有城市。每个城市信仰不同的宗教,如飞天面条神教、隐形独角兽教、绝地教都是常见的信仰。为了方便,我们用不同的正整数代表各种宗教,S 国境内总共有 c 种不同的宗教。

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+1 行两个整数 Wi​,Ci​ 依次表示记录开始之前,城市 i 的评级和信仰。
接下来 N-1 行每行两个整数 x,y 表示一条双向道路。
接下来 Q 行,每行一个操作,格式如上所述。

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

样例
样例输入
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
样例输出
8
9
1
3
数据范围与提示
对所有的数据,N,Q≤10^5, C≤10^5,对所有 QS 和 QM 事件,起点和终点城市的信仰相同;在任意时刻,城市的评级总是不大于 10^4 的正整数,且宗教值不大于 c。

_________________________________________________________________________________________

树链剖分,单点修改,求和。

但是由于只对对应的点(信奉相同的宗教)的点求和,而宗教的种类太多,每个线段树的点不能为10^5个点,所以要动态开点。

第一次写动态开点线段树,但过去用指针写过线段树,所以感觉不算难。

所谓动态开点,就是用不到的点先不要建点,只把对应的点建立,这样每次建一个点只需要建一条链(长logn)就可以了,不用的点先不用建。

其他的和普通线段树一样。

_________________________________________________________________________________________

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef int ll;
  4 const ll maxn=1e5+10;
  5 ll n,m;
  6 struct edge
  7 {
  8     int u,v,nxt;
  9 }e[maxn<<1];
 10 ll head[maxn],js;
 11 void addage(ll u,ll v)
 12 {
 13     e[++js].u=u;e[js].v=v;
 14     e[js].nxt=head[u];head[u]=js;
 15 }
 16 ll w[maxn],c[maxn];
 17 ll dep[maxn],fat[maxn],siz[maxn],son[maxn];
 18 void dfs(ll u,ll fa)
 19 {
 20     dep[u]=dep[fa]+1;
 21     fat[u]=fa;
 22     siz[u]=1;
 23     for(ll i=head[u];i;i=e[i].nxt)
 24     {
 25         ll v=e[i].v;
 26         if(v==fa)continue;
 27         dfs(v,u);
 28         siz[u]+=siz[v];
 29         if(!son[u] || siz[son[u]]<siz[v])son[u]=v;
 30     }
 31 }
 32 ll p,pos[maxn],fos[maxn],top[maxn];
 33 void getpos(ll u,ll fa)
 34 {
 35     pos[u]=++p;
 36     fos[p]=u;
 37     top[u]=fa;
 38     if(!son[u])return ;
 39     getpos(son[u],fa);
 40     for(ll i=head[u];i;i=e[i].nxt)
 41     {
 42         ll v=e[i].v;
 43         if(v!=fat[u] && v!=son[u])getpos(v,v);
 44     }
 45 }
 46 struct node
 47 {
 48     int lc,rc,sm,mx;
 49 }t[2001000];
 50 int rt[maxn],cnt;
 51 void update(ll cur)
 52 {
 53     t[cur].sm=t[t[cur].lc].sm+t[t[cur].rc].sm;
 54     t[cur].mx=max(t[t[cur].lc].mx,t[t[cur].rc].mx);
 55 }
 56 void change(ll & cur,ll l,ll r,ll p,ll x)
 57 {
 58     if(!cur)cur=++cnt;
 59     if(l==r)
 60     {
 61         t[cur].sm=t[cur].mx=x;
 62         return ;
 63     }
 64     ll mid=(l+r)>>1;
 65     if(p<=mid)change(t[cur].lc,l,mid,p,x);
 66     else change(t[cur].rc,mid+1,r,p,x);
 67     update(cur);
 68 }
 69 ll SUM,MAX;
 70 void query(ll cur,ll l,ll r,ll ql,ll qr)
 71 {
 72     if(!cur)return ;
 73     if(ql<=l && r<=qr)
 74     {
 75         SUM+=t[cur].sm;
 76         MAX=max(MAX,t[cur].mx);
 77         return ;
 78     }
 79     ll mid=(l+r)>>1;
 80     if(ql<=mid)query(t[cur].lc,l,mid,ql,qr);
 81     if(mid<qr)query(t[cur].rc,mid+1,r,ql,qr);
 82 }
 83 void ask(ll u,ll v)
 84 {
 85     SUM=0;MAX=0;
 86     ll cl=c[u];
 87     ll tpu=top[u],tpv=top[v];
 88     while(tpu!=tpv)
 89     {
 90         if(dep[tpu]<dep[tpv])
 91         {
 92             swap(u,v);
 93             swap(tpu,tpv);
 94         }
 95         query(rt[cl],1,n,pos[tpu],pos[u]);
 96         u=fat[tpu];tpu=top[u];
 97     }
 98     if(dep[u]>dep[v])swap(u,v);
 99     query(rt[cl],1,n,pos[u],pos[v]);
100 }
101 int main()
102 {
103     scanf("%d%d",&n,&m);
104     for(ll i=1;i<=n;++i)scanf("%d%d",w+i,c+i);
105     for(ll u,v,i=1;i<n;++i)
106     {
107         scanf("%d%d",&u,&v);
108         addage(u,v);addage(v,u);
109     }
110     dfs(1,0);
111     getpos(1,1);
112     for(ll i=1;i<=n;++i)change(rt[c[i]],1,n,pos[i],w[i]);
113     char s[4];
114     ll u,v;
115     while(m--)
116     {
117         scanf("%s%d%d",s,&u,&v);
118         if(s[1]=='W')
119         {
120             w[u]=v;
121             change(rt[c[u]],1,n,pos[u],v);
122         }
123         else if(s[1]=='C')
124         {
125             change(rt[c[u]],1,n,pos[u],0);
126             c[u]=v;
127             change(rt[c[u]],1,n,pos[u],w[u]);
128         }
129         else if(s[1]=='S')
130         {
131             ask(u,v);
132             printf("%d\n",SUM);
133         }
134         else
135         {
136             ask(u,v);
137             printf("%d\n",MAX);
138         }
139     }
140     return 0;
141 }
View Code

 

posted on 2019-03-05 19:48  gryzy  阅读(221)  评论(0编辑  收藏  举报

导航