[luogu P3313] [SDOI2014]旅行

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[luogu P3313] [SDOI2014]旅行相关的知识,希望对你有一定的参考价值。

[luogu P3313] [SDOI2014]旅行

题目描述

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 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
输出样例#1: 复制
8
9
11
3

说明

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

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

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

显然和树剖有关。

然后我们发现宗教信仰有点恶心。

怎么办呢?对于每一种信仰建一棵线段树——>指针实现。

这样的话,我们相当于只需要维护信仰种类棵“动态开点线段树”。

然后相应维护一下几个操作就可以了。

code:

技术分享图片
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #define ms(a,x) memset(a,x,sizeof a)
  5 typedef long long LL;
  6 
  7 void OJ() {
  8     #ifndef ONLINE_JUDGE
  9         freopen("in.txt","r",stdin);
 10         freopen("out.txt","w",stdout);
 11     #endif
 12 }
 13 
 14 namespace fastIO {
 15     #define puc(c) putchar(c)
 16     char ch;
 17     inline int read() {
 18         int x=0,f=1; ch=getchar();
 19         while (ch<0||ch>9) {
 20             if (ch==-) f=-f;
 21             ch=getchar();
 22         }
 23         while (ch>=0&&ch<=9) {
 24             x=(x<<3)+(x<<1)+ch-0;
 25             ch=getchar();
 26         }
 27         return x*f;
 28     }
 29     inline char readc() {
 30         ch=getchar();
 31         while (ch<A||ch>Z) {
 32             ch=getchar();
 33         }
 34         return ch;
 35     }
 36     int cnt,num[20];
 37     template <class T> inline void write(T x) {
 38         if (x==0) {
 39             puc(0); return;
 40         }
 41         for (cnt=0; x; x/=10) num[++cnt]=x%10;
 42         for (; cnt; --cnt) puc(num[cnt]+48);
 43     }
 44     inline void newline() {
 45         puc(\n);
 46     }
 47 } using namespace fastIO;
 48 
 49 const int N=100005;
 50 int n,w[N],c[N],pos[N];
 51 #define sgt node
 52 struct sgt {
 53     node* l,* r;
 54     int s,m;
 55     node () {
 56         l=r=0;
 57         s=m=0;
 58     }
 59     inline void init (node* c) {
 60         c=0;
 61     }
 62     #define max(a,b) ((a)>(b)?(a):(b))
 63     inline void update (node* c) {
 64         c->s=0;
 65         if (c->l) c->s+=c->l->s;
 66         if (c->r) c->s+=c->r->s;
 67         c->m=0;
 68         if (c->l) c->m=max(c->m,c->l->m);
 69         if (c->r) c->m=max(c->m,c->r->m);
 70     }
 71     #define M ((l)+(r)>>1)
 72     inline void modify (node* &c,int l,int r,int x,int w) {
 73         if (l>r) return;
 74         if (!c) c=new node();
 75         if (l==r) {
 76             c->m=w,c->s=w;
 77             return;
 78         }
 79         if (x<=M) modify(c->l,l,M,x,w);
 80         if (x>M) modify(c->r,M+1,r,x,w);
 81         update(c);
 82     }
 83     inline int reply_s (node* &c,int l,int r,int x,int y,int ret=0) {
 84         if (l>y||r<x||!c) return 0;
 85         if (x<=l&&r<=y) return c->s;
 86         if (y<=M) ret=reply_s(c->l,l,M,x,y); else
 87         if (x>M) ret=reply_s(c->r,M+1,r,x,y); else
 88         ret=reply_s(c->l,l,M,x,y)+reply_s(c->r,M+1,r,x,y);
 89         return ret;
 90     }
 91     inline int reply_m (node* &c,int l,int r,int x,int y,int ret=0) {
 92         if (l>y||r<x||!c) return 0;
 93         if (x<=l&&r<=y) return c->m;
 94         if (y<=M) ret=reply_m(c->l,l,M,x,y); else
 95         if (x>M) ret=reply_m(c->r,M+1,r,x,y); else
 96         ret=max(reply_m(c->l,l,M,x,y),reply_m(c->r,M+1,r,x,y));
 97         return ret;
 98     }
 99 } sg,*s[N];
100 class TCP {
101     private:
102         int tot,lnk[N],nxt[N<<1],son[N<<1];
103         int fa[N],dep[N],siz[N],got[N];
104         int clo,dfn[N],top[N];
105     public:
106         inline void init() {
107             tot=0,ms(lnk,0),ms(nxt,0);
108             fa[1]=0,dep[0]=0,siz[0]=0;
109             clo=0;
110         }
111         inline void add(int x,int y) {
112             nxt[++tot]=lnk[x],lnk[x]=tot,son[tot]=y;
113         }
114         inline void dfs(int x,int p) {
115             fa[x]=p,dep[x]=dep[p]+1,siz[x]=1,got[x]=0;
116             for (int j=lnk[x]; j; j=nxt[j]) {
117                 if (son[j]==p) continue;
118                 dfs(son[j],x);
119                 siz[x]+=siz[son[j]];
120                 if (siz[son[j]]>siz[got[x]]) got[x]=son[j];
121             }
122         }
123         inline void redfs(int x,int r) {
124             dfn[x]=++clo,pos[clo]=x,top[x]=r;
125             if (got[x]) redfs(got[x],r);
126             for (int j=lnk[x]; j; j=nxt[j]) {
127                 if (son[j]==fa[x]||son[j]==got[x]) continue;
128                 redfs(son[j],son[j]);
129             }
130         }
131         inline void modify (int c,int x,int w) {
132             sg.modify(s[c],1,n,dfn[x],w);
133         }
134         #define max(a,b) ((a)>(b)?(a):(b))
135         inline int reply_s (int c,int x,int y,int ret=0) {
136             while (top[x]!=top[y]) {
137                 if (dep[top[x]]<dep[top[y]]) std::swap(x,y);
138                 ret+=sg.reply_s(s[c],1,n,dfn[top[x]],dfn[x]);
139                 x=fa[top[x]];
140             }
141             if (dep[x]<dep[y]) std::swap(x,y);
142             ret+=sg.reply_s(s[c],1,n,dfn[y],dfn[x]);
143             return ret;
144         }
145         inline int reply_m (int c,int x,int y,int ret=0) {
146             while (top[x]!=top[y]) {
147                 if (dep[top[x]]<dep[top[y]]) std::swap(x,y);
148                 ret=max(ret,sg.reply_m(s[c],1,n,dfn[top[x]],dfn[x]));
149                 x=fa[top[x]];
150             }
151             if (dep[x]<dep[y]) std::swap(x,y);
152             ret=max(ret,sg.reply_m(s[c],1,n,dfn[y],dfn[x]));
153             return ret;
154         }
155 } t;
156 int m;
157 int main() {
158     OJ(); char opt; int x,y;
159     n=read(),m=read(),t.init();
160     for (int i=1; i<=100000; ++i) sg.init(s[i]);
161     for (int i=1; i<=n; ++i) w[i]=read(),c[i]=read();
162     for (int i=1; i<n; ++i) {
163         x=read(),y=read();
164         t.add(x,y),t.add(y,x);
165     }
166     t.dfs(1,0),t.redfs(1,1);
167     for (int i=1; i<=n; ++i) t.modify(c[i],i,w[i]);
168     for ( ; m; --m) {
169         opt=readc();
170         if (opt==C) {
171             opt=readc(),x=read(),y=read();
172             if (opt==C) {
173                 t.modify(c[x],x,0);
174                 t.modify(c[x]=y,x,w[x]);
175             } else {
176                 t.modify(c[x],x,w[x]=y);
177             }
178         } else {
179             opt=readc(),x=read(),y=read();
180             if (opt==S) {
181                 write(t.reply_s(c[x],x,y));
182                 newline();
183             } else {
184                 write(t.reply_m(c[x],x,y));
185                 newline();
186             }
187         }
188     }
189     return 0;
190 }
View Code

 

以上是关于[luogu P3313] [SDOI2014]旅行的主要内容,如果未能解决你的问题,请参考以下文章

题解SDOI2014旅行

luogu3313 [SDOI2014]旅行

luogu3317 [SDOI2014]重建

luogu_P3313 [SDOI2014]旅行

bzoj3531 [Sdoi2014]旅行

bzoj 3531: [Sdoi2014]旅行