• [loj6498]农民


    对每一个节点用二元组$(p,v)$表示,其中$p$是其是父亲的左(0)还是右(1)儿子,$v$是其父亲的点权

    $x$合法当且仅当:对于其到根路径上所有$(0,v)$都有$a_{x}<v$、$(1,v)$都有$a_{x}>v$

    用树链剖分+线段树来维护这些二元组,即求出$(0,v)$的区间最小值和$(1,v)$的区间最大值即可

    对于翻转,即将区间内(是$k$的子树除去$k$的部分)所有$(p,v)$变为$(poplus 1,v)$,即区间修改,并再维护$(0,v)$的区间最大值和$(1,v)$的区间最小值即可

    (另外翻转后会改变区间,可以再开一棵线段树记录一下每一个点是否被翻转)

    时间复杂度为$o(qlog^{2}n)$

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 100005
      4 #define L (k<<1)
      5 #define R (L+1)
      6 #define mid (l+r>>1)
      7 #define pii pair<int,int>
      8 #define fi first
      9 #define se second
     10 int rt,n,m,p,x,y,a[N],vis[N],ch[N][2],fa[N],sz[N],son[N],dfn[N],top[N],P[N<<2],tag[N<<2];
     11 pii f[N<<2][2];
     12 void dfs1(int k,int f){
     13     if (!k)return;
     14     fa[k]=f;
     15     dfs1(ch[k][0],k);
     16     dfs1(ch[k][1],k);
     17     sz[k]=sz[ch[k][0]]+sz[ch[k][1]]+1;
     18     son[k]=0;
     19     if (sz[ch[k][0]]<sz[ch[k][1]])son[k]=1;
     20 }
     21 void dfs2(int k,int t){
     22     if (!k)return;
     23     dfn[k]=++dfn[0];
     24     top[k]=t;
     25     dfs2(ch[k][son[k]],t);
     26     dfs2(ch[k][son[k]^1],ch[k][son[k]^1]);
     27 }
     28 void update_rev(int k,int l,int r,int x,int y){
     29     if ((l>y)||(x>r))return;
     30     if ((x<=l)&&(r<=y)){
     31         P[k]^=1;
     32         return;
     33     }
     34     update_rev(L,l,mid,x,y);
     35     update_rev(R,mid+1,r,x,y);
     36 }
     37 int query_rev(int k,int l,int r,int x){
     38     if (l==r)return P[k];
     39     if (x<=mid)return query_rev(L,l,mid,x)^P[k];
     40     return query_rev(R,mid+1,r,x)^P[k];
     41 }
     42 pii merge(pii x,pii y){
     43     return make_pair(min(x.fi,y.fi),max(x.se,y.se));
     44 }
     45 void up(int k){
     46     for(int i=0;i<2;i++)f[k][i]=merge(f[L][i],f[R][i]);
     47 }
     48 void upd(int k){
     49     tag[k]^=1;
     50     swap(f[k][0],f[k][1]);
     51 }
     52 void down(int k){
     53     if (tag[k]){
     54         upd(L);
     55         upd(R);
     56         tag[k]=0;
     57     }
     58 }
     59 void update_val(int k,int l,int r,int x,int y,int p){
     60     if (l==r){
     61         f[k][0]=make_pair(y,0);
     62         f[k][1]=make_pair(0x3f3f3f3f,y);
     63         if (p)swap(f[k][0],f[k][1]);
     64         return;
     65     }
     66     down(k);
     67     if (x<=mid)update_val(L,l,mid,x,y,p);
     68     else update_val(R,mid+1,r,x,y,p);
     69     up(k);
     70 }
     71 void update_rev_val(int k,int l,int r,int x,int y){
     72     if ((l>y)||(x>r))return;
     73     if ((x<=l)&&(r<=y)){
     74         upd(k);
     75         return;
     76     }
     77     down(k);
     78     update_rev_val(L,l,mid,x,y);
     79     update_rev_val(R,mid+1,r,x,y);
     80     up(k);
     81 }
     82 pii query_val(int k,int l,int r,int x,int y){
     83     if ((l>y)||(x>r))return make_pair(0x3f3f3f3f,0);
     84     if ((x<=l)&&(r<=y))return f[k][0];
     85     down(k);
     86     return merge(query_val(L,l,mid,x,y),query_val(R,mid+1,r,x,y));
     87 }
     88 void update(int k){
     89     int p=query_rev(1,1,n,dfn[k]);
     90     if (ch[k][0])update_val(1,1,n,dfn[ch[k][0]],a[k],p);
     91     if (ch[k][1])update_val(1,1,n,dfn[ch[k][1]],a[k],p^1);
     92 }
     93 pii query(int k){
     94     pii o=make_pair(0x3f3f3f3f,0);
     95     while (k){
     96         o=merge(o,query_val(1,1,n,dfn[top[k]],dfn[k]));
     97         k=fa[top[k]];
     98     }
     99     return o;
    100 }
    101 int main(){
    102     scanf("%d%d",&n,&m);
    103     for(int i=1;i<=n;i++){
    104         scanf("%d%d%d",&a[i],&ch[i][0],&ch[i][1]);
    105         vis[ch[i][0]]=vis[ch[i][1]]=1;
    106     }
    107     for(int i=1;i<=n;i++)
    108         if (!vis[i])rt=i;
    109     dfs1(rt,0);
    110     dfs2(rt,rt);
    111     update_val(1,1,n,1,0x3f3f3f3f,0);
    112     for(int i=1;i<=n;i++)update(i);
    113     for(int i=1;i<=m;i++){
    114         scanf("%d%d",&p,&x);
    115         if (p==1){
    116             scanf("%d",&a[x]);
    117             update(x);
    118         }
    119         if (p==2){
    120             update_rev(1,1,n,dfn[x],dfn[x]+sz[x]-1);
    121             update_rev_val(1,1,n,dfn[x]+1,dfn[x]+sz[x]-1);
    122         }
    123         if (p==3){
    124             pii o=query(x);
    125             if ((a[x]<o.fi)&&(a[x]>o.se))printf("YES
    ");
    126             else printf("NO
    ");
    127         }
    128     }
    129     return 0;
    130 }
    View Code
  • 相关阅读:
    如何选择合适的MySQL存储引擎
    如何提高Windows操作系统内存利用效率
    jQuery插件 面包屑导航
    [Fireworks+Dreamweaver制作网站]第7课上
    一次完整的安全渗透测试
    jquery插件 跟随屏幕滚动的层
    [Fireworks+Dreamweaver制作网站]第1课
    [Fireworks+Dreamweaver制作网站]第2课
    随笔 幸福
    jQuery插件 jqueryflexselect下拉框自动提示
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14333559.html
Copyright © 2020-2023  润新知