• 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/
    新的风暴已经出现 怎么能够停止不前 穿越时空 竭尽全力 我会来到你身边 微笑面对危险 梦想成真不会遥远 鼓起勇气 坚定向前 奇迹一定会出现

     
  • 相关阅读:
    排序——选择排序和插入排序
    排序——排序的基本概念
    字符串类——KMP算法的应用
    字符串类——KMP子串查找算法
    字符串类——字符串类的创建(下)
    字符串类——字符串类的创建(上)
    数据结构库——链式队列的实现
    P4180 【模板】严格次小生成树[BJWC2010]
    P2511 [HAOI2008]木棍分割
    P2613 【模板】有理数取余
  • 原文地址:https://www.cnblogs.com/whistle13326/p/7356903.html
Copyright © 2020-2023  润新知