[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
113

说明

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 }

时间: 2024-11-05 22:47:22

[luogu P3313] [SDOI2014]旅行的相关文章

[SDOI2014]旅行

洛谷 P3313 [SDOI2014]旅行 https://www.luogu.org/problem/show?pid=3313 题目描述 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. 为了方便,我们用不同的正整数代表各种宗教, S国的居民常常旅行.旅行时他们总会走最短路,并且为了避免麻烦,只在信仰和他们相同的城市留宿.当然旅程的终点也是信仰与他相同的城市.S国政

BZOJ3531: [Sdoi2014]旅行

3531: [Sdoi2014]旅行 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 323  Solved: 192[Submit][Status] Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰.为了方便,我们用不同的正整数代表 各种宗教,  S国的居民常常旅行.旅行时他们总会走最短路,并且为

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

3531: [Sdoi2014]旅行 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 876  Solved: 446[Submit][Status][Discuss] Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰.为了方便,我们用不同的正整数代表 各种宗教,  S国的居民常常旅行.旅行时他们总

【BZOJ 3531】 [Sdoi2014]旅行

3531: [Sdoi2014]旅行 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 575 Solved: 303 [Submit][Status][Discuss] Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰.为了方便,我们用不同的正整数代表各种宗教, S国的居民常常旅行.旅行时他们总会走

luogu P2134 百日旅行

题目链接 luogu P2134 百日旅行 题解 dp方程好想吧 优化有些玄学惹 不会证.... 不过我会三分和贪心 \滑稽 但还是写dp吧 代码 #include<cstdio> #include<cstring> #include<algorithm> inline int read() { int x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9') {if(c == '-') f = -1

【bzoj3531】 [SDOI2014]旅行

题目描述 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰.为了方便,我们用不同的正整数代表各种宗教,  S国的居民常常旅行.旅行时他们总会走最短路,并且为了避免麻烦,只在信仰和他们相同的城市留宿.当然旅程的终点也是信仰与他相同的城市.S国政府为每个城市标定了不同的旅行评级,旅行者们常会记下途中(包括起点和终点)留宿过的城市的评级总和或最大值. 在S国的历史上常会发生以下

[BZOJ 3531][Sdoi2014]旅行(树链剖分+线段树)

Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰.为了方便,我们用不同的正整数代表各种宗教,  S国的居民常常旅行.旅行时他们总会走最短路,并且为了避免麻烦,只在信仰和他们相同的城市留宿.当然旅程的终点也是信仰与他相同的城市.S国政府为每个城市标定了不同的旅行评级,旅行者们常会记下途中(包括起点和终点)留宿过的城市的评级总和或最大值. 在S国的历史

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

题意: S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,城市信仰不同的宗教,为了方便,我们用不同的正整数代表各种宗教. S国的居民常常旅行,只在信仰和他们相同的城市留宿.当然旅程的终点也是信仰与他相同的城市.S国政府为每个城市标定了不同的旅行评级,旅行者们常会记下途中(包括起点和终点)留宿过的城市的评级总和或最大值. 以下几种操作: ? "CC x c":城市x的居民全体改信了c教: ? "CW x w":城市x的评级调整为w: ? "QS x

【题解】SDOI2014旅行

洛谷P3313 大概是一道树链剖分的裸题.可以看出如果不是查询相同宗教的这一点,就和普通的树链剖分毫无两样了.所以针对每一个宗教都单独开一棵线段树,变成单点修改+区间查询.只不过宗教数目很多,空间消耗太大所以只能开一棵总的再动态开点. #include <bits/stdc++.h> using namespace std; #define maxn 200500 #define maxm 2000000 int n, q, cnp = 1, cnt, tot, root[maxn], nam