zoukankan      html  css  js  c++  java
  • 数据结构(括号序列,线段树||点分治,堆):ZJOI 2007 捉迷藏

    【题目描述】

    Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子。某天,Jiajia、Wind和孩子们决定在家里玩捉迷藏游戏。他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这N-1条走廊的分布使得任意两个屋子都互相可达。

    游戏是这样进行的,孩子们负责躲藏,Jiajia负责找,而Wind负责操纵这N个屋子的灯。在起初的时候,所有的灯都没有被打开。每一次,孩子们只会躲 藏在没有开灯的房间中,但是为了增加刺激性,孩子们会要求打开某个房间的电灯或者关闭某个房间的电灯。为了评估某一次游戏的复杂性,Jiajia希望知道 可能的最远的两个孩子的距离(即最远的两个关灯房间的距离)。

    我们将以如下形式定义每一种操作:

    C(hange) i 改变第i个房间的照明状态,若原来打开,则关闭;若原来关闭,则打开。

    G(ame)     开始一次游戏,查询最远的两个关灯房间的距离。

    【输入格式】

    第一行包含一个整数N,表示房间的个数,房间将被编号为1,2,3…N的整数。接下来N-1行每行两个整数a, b,表示房间a与房间b之间有一条走廊相连。接下来一行包含一个整数Q,表示操作次数。接着Q行,每行一个操作,如上文所示。

    【输出格式】

    对于每一个操作Game,输出一个非负整数到hide.out,表示最远的两个关灯房间的距离。若只有一个房间是关着灯的,输出0;若所有房间的灯都开着,输出-1。

    【样例输入】

    8

    1 2

    2 3

    3 4

    3 5

    3 6

    6 7

    6 8

    7

    G

    C 1

    G

    C 2

    G

    C 1

    G

    【样例输出】

    4

    3

    3

    4

    【提示】

    对于20%的数据, N ≤50, M ≤100;

    对于60%的数据, N ≤3000, M ≤10000;

    对于100%的数据, N ≤100000, M ≤500000。

      这道题有三种做法。

      我这里用线段树维护了一个括号序列。

      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 using namespace std;
      5 const int maxn=100010;
      6 const int INF=1000000000;
      7 int cnt,fir[maxn],nxt[maxn*2],to[maxn*2];
      8 void addedge(int a,int b){
      9     nxt[++cnt]=fir[a];
     10     fir[a]=cnt;
     11     to[cnt]=b;
     12 }
     13 int c[maxn];
     14 int ID[maxn],rID[maxn*3],tot;
     15 struct Node{
     16     int a,b,l1,l2,r1,r2,dis;
     17     void Init(int p){
     18         dis=-INF;a=b=0;
     19         if(rID[p]==-2)b=1;
     20         if(rID[p]==-3)a=1;
     21         if(rID[p]>0&&c[rID[p]])
     22             l1=l2=r1=r2=0;
     23         else
     24             l1=l2=r1=r2=-INF;    
     25     }
     26     void Push_up(Node l,Node r){
     27         int a1=l.a,b1=l.b,a2=r.a,b2=r.b;
     28         if(b1>=a2)a=a1,b=b1+b2-a2;
     29         else a=a1+a2-b1,b=b2;
     30         
     31         dis=max(l.dis,r.dis);
     32         dis=max(dis,max(l.r1+r.l2,l.r2+r.l1));
     33         
     34         r1=max(r.r1,max(l.r1+b2-a2,l.r2+a2+b2));
     35         r2=max(r.r2,l.r2+a2-b2);
     36         
     37         l1=max(l.l1,max(a1-b1+r.l1,a1+b1+r.l2));
     38         l2=max(l.l2,r.l2+b1-a1);
     39     }
     40 }tr[(maxn*3)<<2];
     41  
     42 void DFS(int x,int fa){
     43     rID[++tot]=-2;
     44     rID[++tot]=x;
     45     ID[x]=tot;
     46     
     47     for(int i=fir[x];i;i=nxt[i])
     48         if(to[i]!=fa)
     49             DFS(to[i],x);
     50     rID[++tot]=-3;    
     51 }
     52  
     53 void Build(int x,int l,int r){
     54     if(l==r){
     55         tr[x].Init(l);
     56         
     57         return;
     58     }
     59     int mid=(l+r)>>1;
     60     Build(x<<1,l,mid);
     61     Build(x<<1|1,mid+1,r);
     62     tr[x].Push_up(tr[x<<1],tr[x<<1|1]);
     63 }
     64  
     65 void Modify(int x,int l,int r,int g){
     66     if(l==r){
     67         tr[x].Init(l);
     68         return;
     69     }
     70     int mid=(l+r)>>1;
     71     if(mid>=g)Modify(x<<1,l,mid,g);
     72     else Modify(x<<1|1,mid+1,r,g);
     73     tr[x].Push_up(tr[x<<1],tr[x<<1|1]);
     74 }
     75 int n,Q,x;
     76 char op[10];
     77 int main(){
     78 #ifndef ONLINE_JUDGE    
     79     freopen("hide.in","r",stdin);
     80     freopen("hide.out","w",stdout);
     81 #endif
     82     scanf("%d",&n);
     83     for(int i=1;i<=n;i++)c[i]=1;
     84     for(int i=1,a,b;i<n;i++){
     85         scanf("%d%d",&a,&b);
     86         addedge(a,b);
     87         addedge(b,a);
     88     }
     89     
     90     DFS(1,1);
     91     Build(1,1,tot);
     92     
     93     scanf("%d",&Q);
     94     while(Q--){
     95         scanf("%s",op);
     96         if(op[0]=='C'){
     97             scanf("%d",&x);
     98             (c[x])?n--:n++;c[x]^=1;
     99             Modify(1,1,tot,ID[x]);
    100         }
    101         else{
    102             if(n==0)printf("-1
    ");
    103             else if(n==1)printf("0
    ");
    104             else printf("%d
    ",tr[1].dis);
    105         }
    106     }
    107     return 0;
    108 }

      然后我又用点分治+堆的方法AC了一遍。

      先按点分治访问 rt 节点的顺序建 fa 边,每次改一个点只要延 fa 边一路改上去就可以了。 

      关于开三个堆:

      A:最终的答案。

      B:对于每个点,都有一个对应的B类堆,B中最多只有此节点的子节点个数的元素,B中元素为该点子节点的C堆的堆顶。

      C:对于每个点,都有一个对应的C类堆,堆中记录的是每一个子树中的节点对此点的 fa 的贡献。

      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 #include <queue>
      5 using namespace std;
      6 const int maxn=100010;
      7 
      8 struct Heap{
      9     priority_queue<int>A,B;
     10     void Insert(int x){A.push(x);}
     11     void Delete(int x){B.push(x);}
     12     void Pop(){
     13         while(B.size()&&A.top()==B.top())
     14             A.pop(),B.pop();
     15         A.pop();    
     16     }
     17     int Size(){return A.size()-B.size();}
     18     int Max(){
     19         while(B.size()&&A.top()==B.top())
     20             A.pop(),B.pop();
     21         if(!A.size())return 0;
     22         return A.top();
     23     }
     24     int Max2(){
     25         if(Size()<2)return 0;
     26         int p=Max(),ret;Pop();ret=Max();
     27         Insert(p);return ret;
     28     }
     29 }A,B[maxn],C[maxn];
     30 
     31 int fir[maxn],nxt[maxn*2],to[maxn*2],cnt;
     32 void addedge(int a,int b){nxt[++cnt]=fir[a];to[cnt]=b;fir[a]=cnt;}
     33 
     34 int tot,ID[maxn],dep[maxn];
     35 int Min[maxn*3][20],mm[maxn*3];
     36 void DFS(int x,int fa){
     37     Min[ID[x]=++tot][0]=dep[x];
     38     for(int i=fir[x];i;i=nxt[i])
     39         if(to[i]!=fa){
     40             dep[to[i]]=dep[x]+1;
     41             DFS(to[i],x);
     42             Min[++tot][0]=dep[x];
     43         }
     44 }
     45 
     46 int Dis(int x,int y){
     47     if(ID[x]>ID[y])swap(x,y);
     48     int k=mm[ID[y]-ID[x]+1];
     49     int ret=min(Min[ID[x]][k],Min[ID[y]-(1<<k)+1][k]);
     50     return dep[x]+dep[y]-2*ret;
     51 }
     52 
     53 bool vis[maxn];
     54 int sz[maxn],son[maxn],rt,N;
     55 void Get_RT(int x,int fa){
     56     sz[x]=1;son[x]=0;
     57     for(int i=fir[x];i;i=nxt[i]) 
     58         if(!vis[to[i]]&&to[i]!=fa){
     59             Get_RT(to[i],x);
     60             sz[x]+=sz[to[i]];
     61             son[x]=max(son[x],sz[to[i]]);
     62         }
     63     son[x]=max(son[x],N-sz[x]);
     64     if(!rt||son[rt]>son[x])rt=x;    
     65 }
     66 
     67 int fa[maxn];
     68 void Div(int x,int f){
     69     vis[x]=true;fa[x]=f;
     70     for(int i=fir[x];i;i=nxt[i])
     71         if(!vis[to[i]]){
     72             rt=0;N=sz[to[i]];
     73             Get_RT(to[i],0);
     74             Div(rt,x);
     75         }
     76 }
     77 
     78 int light[maxn];
     79 void Turn_OFF(int p,int x){
     80     if(p==x){
     81         B[x].Insert(0);
     82         if(B[x].Size()==2)
     83             A.Insert(B[x].Max());
     84     }
     85     if(!fa[p])return;
     86     int f=fa[p],mx=C[p].Max(),dis=Dis(f,x);
     87     C[p].Insert(dis);
     88     if(mx<dis){
     89         int mt=B[f].Max()+B[f].Max2(),sz=B[f].Size();
     90         if(C[p].Size()!=1)
     91             B[f].Delete(mx);
     92         
     93         B[f].Insert(dis);
     94         if(mt<B[f].Max()+B[f].Max2()){
     95             if(sz>=2)A.Delete(mt);
     96             if(B[f].Size()>=2)A.Insert(B[f].Max()+B[f].Max2());
     97         }
     98     }
     99     Turn_OFF(f,x);    
    100 }
    101 
    102 void Turn_ON(int p,int x){
    103     if(p==x){
    104         B[p].Delete(0);
    105         if(B[p].Size()==1)
    106             A.Delete(B[p].Max());
    107     }
    108     if(!fa[p])return;
    109     int f=fa[p],dis=Dis(f,x),mx;
    110     C[p].Delete(dis);mx=C[p].Max();
    111     if(mx<dis){
    112         int mt=B[f].Max()+B[f].Max2(),sz=B[f].Size();
    113         B[f].Delete(dis);
    114         if(C[p].Size())
    115             B[f].Insert(mx);
    116         if(sz>=2&&mt>B[f].Max()+B[f].Max2()){
    117             if(sz>=2)A.Delete(mt);
    118             if(B[f].Size()>=2)A.Insert(B[f].Max()+B[f].Max2());
    119         }
    120     }
    121     Turn_ON(fa[p],x);
    122 }
    123 
    124 int main(){
    125 #ifndef ONLINE_JUDGE    
    126     freopen("hide.in","r",stdin);
    127     freopen("hide.out","w",stdout);
    128 #endif
    129     int n;
    130     scanf("%d",&n);
    131     for(int i=1,a,b;i<n;i++){
    132         scanf("%d%d",&a,&b);
    133         addedge(a,b);
    134         addedge(b,a);
    135     }
    136     DFS(1,1);mm[0]=-1;
    137     for(int i=1;i<=tot;i++){
    138         if((i&(i-1))==0)mm[i]=mm[i-1]+1;
    139         else mm[i]=mm[i-1];
    140     }
    141     for(int k=1;k<=mm[tot];k++)
    142         for(int i=1;i+(1<<k)-1<=tot;i++)
    143             Min[i][k]=min(Min[i][k-1],Min[i+(1<<(k-1))][k-1]);
    144     N=n;rt=0;
    145     Get_RT(1,0);
    146     Div(rt,0);
    147     
    148     for(int i=1;i<=n;i++)
    149         Turn_OFF(i,i);
    150 
    151     char op[5];
    152     int Q,tot=n,x;
    153     scanf("%d",&Q);
    154     while(Q--){
    155         scanf("%s",op);
    156         if(op[0]=='C'){
    157             scanf("%d",&x);
    158             if(light[x])Turn_OFF(x,x);
    159             else Turn_ON(x,x);
    160             light[x]^=1;
    161         }
    162         else{
    163             if(tot<2)
    164                 printf("%d
    ",tot-1);
    165             else
    166                 printf("%d
    ",A.Max());    
    167         }
    168     }
    169     return 0;
    170 }

      

    尽最大的努力,做最好的自己!
  • 相关阅读:
    Gerrit 系统初探 (已转移到 https://steemit.com/gerrit/@linvictor88/gerrit )
    Iaas概述
    题解西电OJ (Problem 1007 -做一名正气的西电人 )--长整型计算
    题解西电OJ (Problem 1005 -跳舞毯)--动态规划
    题解西电OJ (Problem 1004 -亚特兰提斯)--最小生成树
    题解西电OJ (Problem 1003 -最喜欢的数字)--动态规划
    题解西电OJ (Problem 1008
    题解西电OJ (Problem 1006
    HTML-css selector
    Android--应用开发3(Android layout XML属性)
  • 原文地址:https://www.cnblogs.com/TenderRun/p/5597147.html
Copyright © 2011-2022 走看看