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

来源:互联网 发布:金融大数据 pdf 编辑:程序博客网 时间:2024/05/16 12:00
【题目描述】

 

“大话西游”是一个在中国非常流行的在线游戏,由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 31 2 3 4 51 22 33 44 5QUERY 1CHANGE 1 10QUERY 1

【样例输出】

11110

暴力只有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("\n"); 111     build_tree(1,1,n);112     #define LL long long113     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() {;}
代码

 




原创粉丝点击