COGS 1612. 大话西游 (线段树)

【题目描述】

“大话西游”是一个在中国非常流行的在线游戏,由NIE公司开发和维护。这个游戏来源于著名的小说《西游记》和周星弛的电影,游戏的背景故事充满奇幻色彩,引人入胜。

游戏里面有很多片区域,不同的区域由不同的统治者管辖,其中有一个地方名叫“树国”,由一个妖怪控制着。这里有N个城堡,每个城堡都有其重要程度值(一个正整数,不超过10^8),这些城堡被N-1条双向道路所连接,任意两个城堡均可互达,城堡的重要程度值是可变的。现在,妖怪想知道如果破坏其中的一条道路会发生什么。本题中,你总共需要处理Q条指令,每一个都具有下面所述的格式:

(1)CHANGE

i w

本指令的含义为:将第i个城堡的重要程度值变为w(1<=w<=10^8)

(2)QUERY

j

本指令的含义为:输出min1*max1+min2*max2的值,详细如下:

第j条道路可以把“树国”分成两个连通块,分别称为part1和part2,其中

min1为part1中的最小重要程度值;

max1为part1中的最大重要程度值;

min2为part2中的最小重要程度值;

max2为part2中的最大重要程度值。

【输入格式】

第一行有两个整数N(2<=N<=100000)和Q(1<=Q<=100000),分别表示城堡的个数及指令的数目。

接下来的一行有N个整数(正整数,不超过10^8),表示起初每一个城堡的重要程度值(城堡的编号为1~N)。

接下来有N-1行,每行有两个整数u,v,表示在城堡u和城堡v之间有一条无向边相连,(边的编号依次为1~N-1)。

接下来有Q行,每行有一个指令,格式如下所述。

【输出格式】

对于每个"QUERY"指令,在单独一行输出结果。

【样例输入】

5 3
1 2 3 4 5
1 2
2 3
3 4
4 5
QUERY 1
CHANGE 1 10
QUERY 1

【样例输出】

11
110

暴力只有60 分(不要问我怎么知道,因为我试过了)
那正解就是线段树维护dfs序
因为dfs序是有序的 深搜嘛。。
然后操作就是 单点修改+区间求最值

至于断边的时候自己画画吧

  1 #include <ctype.h>
  2 #include <cstdio>
  3 
  4 const int MAXN=200010;
  5 
  6 int n,q,num;
  7 
  8 int a[MAXN],siz[MAXN],id[MAXN],dfn[MAXN],pre[MAXN];
  9 
 10 struct node {
 11     int to;
 12     int th;
 13     int next;
 14 };
 15 node e[MAXN];
 16 
 17 int head[MAXN],tot=1;
 18 
 19 struct data {
 20     int l,r;
 21     int mn,mx;
 22 };
 23 data t[MAXN<<2];
 24 
 25 char s[10];
 26 
 27 void read(int&x) {
 28     register char c=getchar();
 29     for(x=0;!isdigit(c);c=getchar());
 30     for(;isdigit(c);x=x*10+c-48,c=getchar());
 31 }
 32         
 33 void add(int x,int y,int now) {
 34     e[++tot].to=y;
 35     e[tot].th=now;
 36     e[tot].next=head[x];
 37     head[x]=tot;
 38     }
 39     
 40 int min(int a,int b) {return a<b?a:b;}
 41         
 42 int max(int a,int b) {return a<b?b:a;}
 43 
 44 void dfs(int now,int fa) {
 45     siz[now]=1;dfn[now]=++num;id[num]=now;
 46     for(int i=head[now];i;i=e[i].next) {
 47         int to=e[i].to;
 48         if(to==fa) continue;
 49         pre[e[i].th]=to;
 50         dfs(to,now);
 51         siz[now]+=siz[to];
 52     }
 53 }
 54 
 55 void build_tree(int now,int l,int r) {
 56     t[now].l=l;t[now].r=r;
 57     if(l==r) {
 58         t[now].mn=t[now].mx=a[id[l]];
 59         return;
 60     }
 61     int mid=(r+l)>>1;
 62     build_tree(now<<1,l,mid);
 63     build_tree(now<<1|1,mid+1,r);
 64     t[now].mn=min(t[now<<1].mn,t[now<<1|1].mn);
 65     t[now].mx=max(t[now<<1].mx,t[now<<1|1].mx);
 66 }
 67 
 68 void modify(int now,int x,int val) {
 69     if(t[now].l==t[now].r) {
 70         t[now].mn=t[now].mx=val;
 71         return;
 72     }
 73     int mid=(t[now].l+t[now].r)>>1;
 74     if(x<=mid) modify(now<<1,x,val);
 75     if(x>mid) modify(now<<1|1,x,val);
 76     t[now].mn=min(t[now<<1].mn,t[now<<1|1].mn);
 77     t[now].mx=max(t[now<<1].mx,t[now<<1|1].mx);
 78 }
 79 
 80 int query_mn(int now,int l,int r) {
 81     if(l<=t[now].l&&r>=t[now].r) return t[now].mn;
 82     int mn1=1e9,mn2=1e9;
 83     int mid=(t[now].l+t[now].r)>>1;
 84     if(l<=mid) mn1=min(mn1,query_mn(now<<1,l,r));
 85     if(r>mid) mn2=min(mn2,query_mn(now<<1|1,l,r));
 86     return mn1<mn2?mn1:mn2;
 87 }
 88 
 89 int query_mx(int now,int l,int r) {
 90     if(l<=t[now].l&&r>=t[now].r) return t[now].mx;
 91     int mx1=-1,mx2=-1;
 92     int mid=(t[now].l+t[now].r)>>1;
 93     if(l<=mid) mx1=max(mx1,query_mx(now<<1,l,r));
 94     if(r>mid) mx2=max(mx2,query_mx(now<<1|1,l,r));
 95     return mx1<mx2?mx2:mx1;
 96 }
 97 
 98 int hh() {
 99     freopen("westward.in","r",stdin);
100 //    freopen("westward.out","w",stdout);
101     int x,y;
102     read(n);read(q);
103     for(int i=1;i<=n;++i) read(a[i]);
104     for(int i=1;i<n;++i) {
105         read(x);read(y);
106         add(x,y,i);add(y,x,i);
107     }
108     dfs(1,0);
109     for(int i=1;i<=n;++i) printf("%d ",dfn[i]);
110     printf("
"); 
111     build_tree(1,1,n);
112     #define LL long long
113     for(int i=1;i<=q;++i) {
114         scanf("%s",s);
115         if(s[0]=='C') {
116             read(x);read(y);
117             modify(1,dfn[x],y);
118         }
119         else {
120             read(x);
121             int l=dfn[pre[x]],r=l+siz[pre[x]]-1;
122             int min1=query_mn(1,l,r),max1=query_mx(1,l,r);
123             int min2,max2;
124             if(l!=1) min2=query_mn(1,1,l-1),max2=query_mx(1,1,l-1);
125             if(r!=n) min2=min(min2,(query_mn(1,r+1,n))),max2=max(max2,query_mx(1,r+1,n));
126             LL ans=(LL)min1*(LL)max1+(LL)min2*(LL)max2;
127             printf("%lld
",ans);
128         }
129     }
130     return 0;
131 }
132 
133 int sb=hh();
134 int main() {;}
代码




作者:乌鸦坐飞机
出处:http://www.cnblogs.com/whistle13326/
新的风暴已经出现 怎么能够停止不前 穿越时空 竭尽全力 我会来到你身边 微笑面对危险 梦想成真不会遥远 鼓起勇气 坚定向前 奇迹一定会出现

 
原文地址:https://www.cnblogs.com/whistle13326/p/7356903.html