zoukankan      html  css  js  c++  java
  • bzoj 1095 [ZJOI2007]Hide 捉迷藏(括号序列+线段树)

    【题目链接】

        http://www.lydsy.com/JudgeOnline/problem.php?id=1095

    【题意】

        给定一棵树,树上颜色或白或黑而且可以更改,多个询问求最远黑点之间的距离。

    【思路】

        括号序列+线段树

      对树进行一遍dfs我们可以得到一个括号序列。如:

          [A[B[E][F[H][I]]][C][D[G]]]

      E和G之间去掉匹配的括号和字母之后的串就是:

        ]][[

        把它看作一个二元组(a,b)表示有a个]和b个[,而且这个二元组的形式一定是…]]]][[[…的,则E G之间的距离为a+b。

        线段树维护:每个节点维护7个值如下

        a,b:分别表示]和[的数量

        dis:max{ a+b } S’为S子串

        l1:max{ a+b } S’为S的后缀,且S’紧跟在一个黑色点之后

        l2:max{ b-a } S’为S的后缀,且S’紧跟在一个黑色点之后

        r1:max{ a+b } S’为S的前缀,且一个黑色点紧跟在S’之后

        r2:max{ a-b } S’为S的前缀,且一个黑色点紧跟在S’之后

        合并线段树的左右儿子L和R:

        dis=max{ L.dis,R.dis,L.a+R.b+|L.b-R.a| }

            =max{ L.dis,R.dis,max{ L.r1+R.l2,L.r2+R.l1 } }

        //R’定义为R的前缀,且一个黑色点紧跟在R’之后

      l1=max{ L.l1 , L.a+R’.b+|L.b-R’.a| }

           =max{ L.l1 , max{ R.l2+L.a+L.b , R.l1+L.a-L.b } }

        l2=max{ L.l2 , max{ R’.b+L.b-R’.a-L.a  ,  R’.b-L.a-R’.a+L.b } }

           =max{ L.l2 , R.l2+L.b-L.a  }

        r1与r2的[推倒]同理,此处略去,直接给出:

        r1=max{ R.r1 , max{ L.r1,R.a+R.b , L.r2+R.a+R.b } }

      r2=max{ R.r2 , L.r2+R.a-R.b }

    【代码】

      1 #include<set>
      2 #include<map>
      3 #include<cmath>
      4 #include<cstdio>
      5 #include<cstring>
      6 #include<iostream>
      7 #include<algorithm>
      8 #define FOR(a,b,c) for(int a=b;a<=c;a++)
      9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
     10 using namespace std;
     11 
     12 typedef long long ll;
     13 const int N = 1e6+10;
     14 const int inf = 1<<25;    //不要太大 
     15 
     16 ll read() {
     17     char c=getchar();
     18     ll f=1,x=0;
     19     while(!isdigit(c)) {
     20         if(c=='-') f=-1; c=getchar();
     21     }
     22     while(isdigit(c))
     23         x=x*10+c-'0',c=getchar();
     24     return x*f;
     25 }
     26 
     27 int n,q,tot;
     28 int vis[N],num[N],pos[N];
     29 
     30 struct Edge { int v,nxt;
     31 }e[N<<1];
     32 int en=1,front[N];
     33 void adde(int u,int v) 
     34 {
     35     e[++en]=(Edge){v,front[u]}; front[u]=en;
     36 }
     37 
     38 struct Tnode {
     39     int a,b,dis,l1,l2,r1,r2;
     40     void val(int x) {
     41         a=b=0;
     42         dis=l1=l2=r1=r2=-inf;
     43         if(x==-1) b=1;
     44         else if(x==-2) a=1;
     45         else if(vis[x]==1) l1=l2=r1=r2=0; 
     46     }
     47     void merge(Tnode L,Tnode R) {
     48         a=L.a+max(0,R.a-L.b);
     49         b=R.b+max(0,L.b-R.a);
     50         dis=max(max(L.dis,R.dis),max(L.r1+R.l2,L.r2+R.l1));
     51         l1=max(L.l1,max(R.l1-L.b+L.a,R.l2+L.b+L.a));
     52         l2=max(L.l2,R.l2+L.b-L.a);
     53         r1=max(R.r1,max(L.r1-R.a+R.b,L.r2+R.a+R.b));
     54         r2=max(R.r2,L.r2+R.a-R.b);
     55     }
     56 }T[N<<1];
     57 
     58 void build(int u,int l,int r) 
     59 {
     60     if(l==r) T[u].val(num[l]);
     61     else {
     62         int mid=(l+r)>>1;
     63         build(u<<1,l,mid);
     64         build(u<<1|1,mid+1,r);
     65         T[u].merge(T[u<<1],T[u<<1|1]);
     66     }
     67 }
     68 void update(int u,int l,int r,int rk) 
     69 {
     70     if(l==r) T[u].val(num[l]);
     71     else {
     72         int mid=(l+r)>>1;
     73         if(rk<=mid) update(u<<1,l,mid,rk);
     74         else update(u<<1|1,mid+1,r,rk);
     75         T[u].merge(T[u<<1],T[u<<1|1]);
     76     }
     77 }
     78 
     79 void dfs(int u,int fa) 
     80 {
     81     num[++tot]=-1;
     82     pos[num[++tot]=u]=tot;
     83     trav(u,i) if(e[i].v!=fa) 
     84         dfs(e[i].v,u);
     85     num[++tot]=-2;
     86 }
     87 
     88 int main()
     89 {
     90     n=read();
     91     int cnt=n;
     92     FOR(i,1,n) vis[i]=1;
     93     FOR(i,1,n-1) {
     94         int u=read(),v=read();
     95         adde(u,v),adde(v,u);
     96     }
     97     dfs(1,-1);
     98     build(1,1,tot);
     99     q=read();
    100     char op[5]; int x;
    101     while(q--) {
    102         scanf("%s",op);
    103         if(op[0]=='G') {
    104             if(cnt==0) puts("-1");
    105             else if(cnt==1) puts("0");
    106             else printf("%d
    ",T[1].dis);
    107         }
    108         else {
    109             x=read();
    110             cnt+=vis[x]=-vis[x];
    111             update(1,1,tot,pos[x]);
    112         }
    113     }
    114     return 0;
    115 }

    Cqx论文 click here

  • 相关阅读:
    redis数据结构
    XMAPP 的安装与配置
    Android 工具类 异常处理类CrashHandler
    Android Config通用类来记录信息
    Android AppUtil通用类
    Android 用Chrome浏览器打开url 自定义样式
    Diycode开源项目 如何解决InputMethodManager造成的内存泄漏问题
    Diycode开源项目 SitesListFragment分析
    Diycode开源项目 NodeListFragment分析
    Diycode开源项目 搭建可以具有下拉刷新和上拉加载的Fragment
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5277336.html
Copyright © 2011-2022 走看看