“大话西游”是一个在中国非常流行的在线游戏,由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序是有序的 深搜嘛。。
然后操作就是 单点修改+区间求最值
至于断边的时候自己画画吧
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
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("\n"); 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\n",ans); 128 } 129 } 130 return 0; 131 } 132 133 int sb=hh(); 134 int main() {;}