zoukankan      html  css  js  c++  java
  • 1095: [ZJOI2007]Hide 捉迷藏

    题意:给定一棵树,每个节点可以变成黑白两色。一开始所有节点都是黑色,操作可将点颜色改变,询问当前情况下距离最远的两个黑点的距离。

    动态树分治。一开始想的是对于每个节点维护主大和次大,后来发现这实在是太NAIVE了。实际上,正解是这样的:

    对于每个点,维护两个堆(接下来说的都是点分树上的节点):第一个堆,该点子树到该点父亲的距离,第二个堆,该点直接儿子的第一个堆的堆顶元素。

    然后我们再开一个全局堆,即答案堆,维护所有第二个堆最大和次大之和。每次询问只要把堆顶元素拿出来就可以了。

    为什么空间开的下呢?这个道理和震波那道题是一样的,考虑点分治的时间复杂度,每个点最大堆空间开到的就是该点子树大小,总和是nlogn的,完全开的下。

    怎么修改呢,暴力爬树高啊,点分树不就是这一点树高稳定log最好吗!

    维护3个堆的过程特别繁琐,写的时候写了一个上午。。。就为了那几个if。。

    最后被自己模拟的堆坑了一发。。改到现在才过

    上代码

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 100005
      4 #define INF 1e9
      5 inline int read(){
      6     int x=0,f=1; char a=getchar();
      7     while(a<'0' || a>'9') {if(a=='0') f=-1; a=getchar();}
      8     while(a>='0' && a<='9') x=x*10+a-'0',a=getchar();
      9     return x*f;
     10 }
     11 int n,q,head[N],s[N],cnt,f[N],rt,sz,dep[N],fa[N][20],dis[N][20],now;
     12 char ch[2]; bool vis[N],on[N];
     13 struct heap{
     14     priority_queue<int>A,B;
     15     void push(int x) {A.push(x);}
     16     void erase(int x) {B.push(x);}
     17     void pop() {while(B.size()&&A.top()==B.top()) A.pop(),B.pop(); A.pop();}
     18     int top() {while(B.size()&&A.top()==B.top()) A.pop(),B.pop(); if(A.size()) return A.top(); else return -INF;}
     19     int size() {return A.size()-B.size();}
     20     int s_top(){ if(size()<2) return -INF; 
     21         while(B.size()&&A.top()==B.top()) A.pop(),B.pop();
     22         int t=A.top(),ret; A.pop(); 
     23         while(B.size()&&A.top()==B.top()) A.pop(),B.pop();
     24         ret=A.top(); A.push(t); 
     25         return ret;
     26     }
     27 }C,A[N],B[N];
     28 struct edges{
     29     int to,next;
     30 }e[2*N];
     31 void insert(){
     32     int u=read(),v=read();
     33     e[cnt]=(edges){v,head[u]};head[u]=cnt++;
     34     e[cnt]=(edges){u,head[v]};head[v]=cnt++;
     35 }
     36 void getroot(int x,int p){
     37     s[x]=1; f[x]=0;
     38     for(int i=head[x];i>=0;i=e[i].next){
     39         if(vis[e[i].to] || p==e[i].to) continue;
     40         getroot(e[i].to,x); s[x]+=s[e[i].to];
     41         f[x]=max(f[x],s[e[i].to]);
     42     }
     43     f[x]=max(f[x],sz-s[x]);
     44     if(f[rt]>f[x]) rt=x;
     45 }
     46 void getship(int x,int anc,int p,int d){
     47     for(int v,i=head[x];i>=0;i=e[i].next){
     48         v=e[i].to;
     49         if(vis[v] || p==v) continue;
     50         fa[v][++dep[v]]=anc; dis[v][dep[v]]=d; getship(v,anc,x,d+1);
     51     }
     52 }
     53 void buildtree(int x){
     54     vis[x]=1; getship(x,x,0,1); int all=sz;
     55     for(int i=head[x];i>=0;i=e[i].next){
     56         if(vis[e[i].to]) continue;
     57         if(s[e[i].to]>s[x]) s[e[i].to]=all-s[x]; sz=s[e[i].to];
     58         rt=0; getroot(e[i].to,x); buildtree(rt);
     59     }
     60 }
     61 void turn_off(int x){
     62      B[x].push(0);
     63      if(B[x].size()==2) C.push(B[x].top());
     64      for(int t,pre,i=dep[x];i>1;i--){
     65          if(!A[fa[x][i]].size()){
     66              A[fa[x][i]].push(dis[x][i-1]);
     67              pre=B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top();
     68             B[fa[x][i-1]].push(dis[x][i-1]);
     69             if(pre>0 && pre==B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top()) continue;
     70              if(pre>0 && pre!=B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top())
     71              C.erase(pre),C.push(B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top());
     72              else if(B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top()>0) C.push(B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top());
     73          }else{
     74              t=A[fa[x][i]].top(); A[fa[x][i]].push(dis[x][i-1]);
     75             if(t<dis[x][i-1]){ 
     76                 pre=B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top(); 
     77                 B[fa[x][i-1]].erase(t); B[fa[x][i-1]].push(dis[x][i-1]); 
     78                 if(pre>0 && pre!=B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top())
     79                 C.erase(pre),C.push(B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top());
     80             }
     81          }
     82      }
     83 }
     84 void turn_on(int x){
     85     B[x].erase(0);
     86     if(B[x].size()==1) C.erase(B[x].top());
     87     for(int t,pre,i=dep[x];i>1;i--){
     88         A[fa[x][i]].erase(dis[x][i-1]);
     89         if(A[fa[x][i]].top()<dis[x][i-1]) {
     90             pre=B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top();
     91             B[fa[x][i-1]].erase(dis[x][i-1]); 
     92             if(A[fa[x][i]].size()) B[fa[x][i-1]].push(A[fa[x][i]].top());
     93             if(pre>0) {
     94                 if(pre==B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top()) continue;
     95                 C.erase(pre);
     96                 if(B[fa[x][i-1]].size()>1)
     97                 C.push(B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top());
     98             }
     99         }
    100     }
    101 }
    102 inline void change(int x){
    103     if(!on[x]) turn_on(x);
    104     else turn_off(x);
    105     on[x]^=1; 
    106     if(on[x]) now++;
    107     else now--;
    108 }
    109 int main(){
    110     n=read(); memset(head,-1,sizeof(head));
    111     for(int i=1;i<n;i++) insert();
    112     f[0]=INF; sz=n; getroot(1,0); buildtree(rt);
    113     for(int i=1;i<=n;i++) fa[i][++dep[i]]=i,turn_off(i);
    114     q=read();
    115     while(q--){
    116         scanf("%s",ch);
    117         if(ch[0]=='G') {
    118             if(now==n) puts("-1");
    119             else printf("%d
    ",max(C.top(),0));
    120         }
    121         else change(read()); 
    122     }
    123     return 0;
    124 }
  • 相关阅读:
    简单介绍 CPU 的工作原理
    Converting a MatchCollection to string array
    Ubuntu18.04安装pycharm如何显示锁定图标到收藏夹
    MFC使用控制台
    将CString输出到控制台的方法
    Python 字符串前面加u,r,b的含义
    Converting a MatchCollection to string array
    git命令查看版本记录
    git命令查看版本记录
    SQL Server游标
  • 原文地址:https://www.cnblogs.com/enigma-aw/p/6214487.html
Copyright © 2011-2022 走看看