【BZOJ3531】【SDOI2014】旅行

题目传送门

题目大意:给定一棵无根树,每个节点有自己的类别和权值,现在给定两个类别相同的点,叫你求这2点路径上同类别节点的权值和/最大权值。

节点类别与权值会改变。

解题思路:考虑对每一个类别开一棵线段树,动态开点,可以写指针,也可以开数组写链表,然后剩下的就是树剖的东西了。我写的是指针,跑的略慢一些,时间效率为\( O(q \log^{2} n) \).

代码由于是在自家的mac上码的,所以和以前风格不大一样。

  1 #include <stdio.h>
  2 #define MN 100005
  3 inline void swp(int &a,int &b){a ^= b ^= a ^= b;}
  4 inline int max(int a,int b){return a > b ? a : b;}
  5 inline int in(){
  6     int x = 0 ,f = 1; char ch = getchar();
  7     while (ch < ‘0‘ || ch > ‘9‘) f = ch==‘-‘ ? -1 :1 , ch = getchar();
  8     while (ch >= ‘0‘ && ch <= ‘9‘ ) x = (x<<3) + (x<<1) + ch - ‘0‘,ch = getchar();
  9     return x*f;
 10 }
 11 struct segment_tree{
 12     segment_tree *ls , *rs;
 13     int sum,ma;
 14     void combine(){
 15         sum = ma = 0;
 16         if (ls != NULL){
 17             sum += ls -> sum;
 18             ma = max( ma , ls -> ma );
 19         }if (rs != NULL){
 20             sum += rs -> sum;
 21             ma = max( ma , rs -> ma );
 22         }
 23     }
 24     segment_tree (int sum=0,int ma=0):sum(sum),ma(ma){ls = rs = NULL;}
 25 }*ST[MN];
 26 #define S_T segment_tree
 27 int to[MN<<1],nxt[MN<<1],cnt,head[MN];
 28 int n,q,top[MN],siz[MN],son[MN],val[MN],belief[MN],fa[MN],dep[MN],pos[MN],dfsn;
 29 inline void ins(int x,int y){to[++cnt] = y , nxt[cnt] = head[x] , head[x] = cnt;}
 30 inline void insw(int x,int y){ins(x,y); ins(y,x);}
 31 inline void dfs1(int u,int f,int d){
 32     siz[u] = 1; dep[u] = d; fa[u] = f;
 33     for (register int i = head[u]; i; i = nxt[i])
 34         if (to[i] != f) {
 35             dfs1(to[i],u,d+1); siz[u] += siz[to[i]];
 36             if (siz[son[u]] < siz[to[i]]) son[u] = to[i];
 37         }
 38 }
 39 inline void dfs2(int u,int tp){
 40     top[u] = tp; pos[u] = (++dfsn); if (son[u]) dfs2(son[u],tp);
 41     for (register int i = head[u]; i; i = nxt[i])
 42         if (to[i] != fa[u] && to[i] != son[u]) dfs2(to[i],to[i]);
 43 }
 44 #define mid (l+r>>1)
 45 inline void insert(S_T* &x,int l,int r,int pos,int val){
 46     if (x == NULL) x = new S_T;
 47     if (l == r){x -> sum = x -> ma = val; return;}
 48     if (pos <= mid) insert(x -> ls,l,mid,pos,val);
 49     else insert(x -> rs,mid+1,r,pos,val);x->combine();
 50 }
 51 inline void Delete(S_T* &x,int l,int r,int pos){
 52     if (l==r){delete x; x = NULL; return; }
 53     if (pos<=mid) Delete(x -> ls,l,mid,pos);
 54     else Delete(x -> rs,mid+1,r,pos);
 55     if (x -> ls == NULL && x -> rs == NULL){delete x; x = NULL; return; }
 56     else x -> combine();
 57 }
 58 inline int QM(S_T* &x,int l,int r,int a,int b){
 59     if (x == NULL) return 0;
 60     if (l == a && r == b) return x -> ma;
 61     if (b<=mid) return QM(x -> ls,l,mid,a,b);
 62     if (a>mid) return QM(x -> rs,mid+1,r,a,b);
 63     return max(QM(x -> ls,l,mid,a,mid),QM(x -> rs,mid+1,r,mid+1,b));
 64 }
 65 inline int QS(S_T* &x,int l,int r,int a,int b){
 66     if (x == NULL) return 0;
 67     if (l == a && r == b) return x -> sum;
 68     if (b<=mid) return QS(x -> ls,l,mid,a,b);
 69     if (a>mid) return QS(x -> rs,mid+1,r,a,b);
 70     return QS(x -> ls,l,mid,a,mid)+QS(x -> rs,mid+1,r,mid+1,b);
 71 }
 72 inline int qm(int belief,int x,int y){
 73     register int res = 0;
 74     while (top[x] != top[y]){
 75         if (dep[top[x]] < dep[top[y]]) swp(x,y);
 76         res = max(res,QM(ST[belief],1,n,pos[top[x]],pos[x]));
 77         x = fa[top[x]];
 78     }if (dep[x] > dep[y]) swp(x,y);res = max(res,QM(ST[belief],1,n,pos[x],pos[y]));
 79     return res;
 80 }
 81 inline int qs(int belief,int x,int y){
 82     register int res = 0;
 83     while (top[x] != top[y]){
 84         if (dep[top[x]] < dep[top[y]]) swp(x,y);
 85         res += QS(ST[belief],1,n,pos[top[x]],pos[x]);
 86         x = fa[top[x]];
 87     }if (dep[x] > dep[y]) swp(x,y);res += QS(ST[belief],1,n,pos[x],pos[y]);
 88     return res;
 89 }
 90 void init(){
 91     n = in() , q = in();
 92     for (int i = 1; i <= n; ++i) val[i] = in() , belief[i] = in();
 93     for (register int i = 1; i < n; ++i) insw(in(),in());
 94     dfs1(1,1,1);dfs2(1,1);
 95     for (register int i = 1; i <= n; ++i)
 96         insert(ST[belief[i]],1,n,pos[i],val[i]);
 97 }
 98 void solve(){
 99     while(q--){
100         register char op[5]; scanf("%s",op);
101         register int x=in(),y=in();
102         if (op[0] == ‘C‘){
103             if (op[1] == ‘C‘){
104                 Delete(ST[belief[x]],1,n,pos[x]);
105                 insert(ST[belief[x] = y],1,n,pos[x],val[x]);
106             }else insert(ST[belief[x]],1,n,pos[x],val[x]=y);
107         }else{
108             if (op[1] == ‘M‘) printf("%d\n",qm(belief[x],x,y));
109             else printf("%d\n",qs(belief[x],x,y));
110         }
111     }
112 }
113 int main(){ init(); solve();}
时间: 2024-10-16 15:22:36

【BZOJ3531】【SDOI2014】旅行的相关文章

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国的居民常常旅行.旅行时他们总会走最短路,并且为

【块状树】【树链剖分】【线段树】bzoj3531 [Sdoi2014]旅行

离线后以宗教为第一关键字,操作时间为第二关键字排序. <法一>块状树,线下ac,线上tle…… #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<queue> using namespace std; queue<int>q; int f,c; inline void R(int &x){ c=0;f=1;

BZOJ3531 SDOI2014 旅行 - 树链剖分,主席树

题意:给定一棵树,树上每个点有权值和类型.支持:修改某个点的类型:修改某个点的权值:询问某条链上某个类型的点的和/最大值.点数/类型数/询问数<=100000. 分析: 树链剖分,对每个类型的点建立线段树(动态开点). note: 忘记写t_query返回值调半天-- 莫名其妙地1A 代码: 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int a[5000005],s[5000005],dep[100005],size[10

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国的居民常常旅行.旅行时他们总

[SDOI2014]旅行

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

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

【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