• 【SPOJ-QTREE3】树链剖分


    http://www.spoj.com/problems/QTREE3/

     时间限制:2s    代码长度限制:50000B     内存限制:1536MB

    【题目描述】

    给出N个点的一棵树(N-1条边),节点有白有黑,初始全为白

    有两种操作:

    0 i : 改变某点的颜色(原来是黑的变白,原来是白的变黑)

    1 v : 询问1到v的路径上的第一个黑点,若无,输出-1

     

    总共有12组数据。

    1/3 的数据, N=5000, Q=400000.

    1/3 的数据, N=10000, Q=300000.

    1/3 的数据,N=100000, Q=100000.

     

    【输入格式】

    单组数据的。

    第一行 N and Q.表示N个点和Q个操作

    下来N-1条无向边

    下来 Q行,每行一个操作"0 i" 或者"1 v" (1 ≤ i, v ≤ N).

     

    【输出格式】

     

    遇到 "1 v"操作的时候,输出结果。

     

    这题就是树链剖分,线段树维护当前区间最左边的黑点的编号因为是单点修改,所以根本不用lazy,也不用记录点的颜色(看它所维护的最左边的点这个值是否为0)。

     

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 using namespace std;
      6 
      7 const int N=1000100;
      8 struct trnode{
      9     int lc,rc,l,r,c,d,lazy;
     10 }t[2*N];
     11 struct node{
     12     int x,y,next;
     13 }a[2*N];
     14 int n,m,tl,z,len;
     15 int first[N],tot[N],son[N],fa[N],dep[N],ys[N],yss[N],top[N];
     16 
     17 void ins(int x,int y)
     18 {
     19     len++;
     20     a[len].x=x;a[len].y=y;
     21     a[len].next=first[x];first[x]=len;
     22 }
     23 
     24 int maxx(int x,int y){return x>y ? x:y;}
     25 int minn(int x,int y){return x<y ? x:y;}
     26 
     27 int build_tree(int l,int r)
     28 {
     29     int x=++tl;
     30     t[x].l=l;t[x].r=r;
     31     t[x].c=t[x].d=t[x].lazy=0;
     32     t[x].lc=t[x].rc=0;
     33     if(l<r)
     34     {
     35         int mid=(l+r)>>1;
     36         t[x].lc=build_tree(l,mid);
     37         t[x].rc=build_tree(mid+1,r);
     38     }
     39     return x;
     40 }
     41 
     42 void change(int x,int p)
     43 {
     44     int lc=t[x].lc,rc=t[x].rc,mid=(t[x].l+t[x].r)>>1;
     45     if(t[x].l==t[x].r) 
     46     {
     47         if(t[x].d==0) t[x].d=t[x].l;
     48         else t[x].d=0;
     49         return;
     50     }
     51     if(p<=mid) change(lc,p);
     52     else change(rc,p);
     53     if(t[lc].d) t[x].d=t[lc].d;
     54     else if(t[rc].d) t[x].d=t[rc].d;
     55     else t[x].d=0;
     56 }
     57 
     58 int query(int x,int l,int r)
     59 {
     60     if(t[x].l==l && t[x].r==r) return t[x].d;
     61     int lc=t[x].lc,rc=t[x].rc,mid=(t[x].l+t[x].r)>>1;
     62     if(r<=mid) return query(lc,l,r);
     63     else if(l>mid) return query(rc,l,r);
     64     else
     65     {
     66         int t1=query(lc,l,mid);
     67         if(t1) return t1;
     68         int t2=query(rc,mid+1,r);
     69         if(t2) return t2;
     70         return 0;
     71     }
     72 }
     73 
     74 void dfs1(int x)
     75 {
     76     tot[x]=1;son[x]=0;
     77     for(int i=first[x];i;i=a[i].next)
     78     {
     79         int y=a[i].y;
     80         if(y==fa[x]) continue;
     81         fa[y]=x;
     82         dep[y]=dep[x]+1;
     83         dfs1(y);
     84         if(tot[son[x]]<tot[y]) son[x]=y;
     85         tot[x]+=tot[y];
     86     }
     87 }
     88 
     89 void dfs2(int x,int tp)
     90 {
     91     ys[x]=++z;yss[z]=x;top[x]=tp;
     92     if(son[x]) dfs2(son[x],tp);
     93     for(int i=first[x];i;i=a[i].next)
     94     {
     95         int y=a[i].y;
     96         if(y==fa[x] || y==son[x]) continue;
     97         dfs2(y,y);
     98     }
     99 }
    100 
    101 int solve(int y)
    102 {
    103     int ty=top[y],ans=-1;
    104     while(ty!=1)
    105     {
    106         int t=query(1,ys[ty],ys[y]);
    107         if(t) ans=yss[t];
    108         y=fa[ty];ty=top[y];
    109     }
    110     int t;
    111     if(y==1) t=query(1,1,1);
    112     else t=query(1,1,ys[y]);
    113     if(t) ans=yss[t];
    114     return ans;
    115 }
    116 
    117 int main()
    118 {
    119     freopen("a.in","r",stdin);
    120     // freopen("me.out","w",stdout);
    121     scanf("%d%d",&n,&m);
    122     tl=0;len=0;z=0;
    123     memset(first,0,sizeof(first));
    124     for(int i=1;i<n;i++)
    125     {
    126         int x,y;
    127         scanf("%d%d",&x,&y);
    128         ins(x,y),ins(y,x);
    129     }
    130     build_tree(1,n);
    131     fa[1]=0;dep[1]=1;dfs1(1);
    132     dfs2(1,1);
    133     for(int i=1;i<=m;i++)
    134     {
    135         int tmp,x;
    136         scanf("%d%d",&tmp,&x);
    137         if(!tmp) change(1,ys[x]);
    138         else 
    139         {
    140             int ans=solve(x);
    141             if(ans) printf("%d
    ",ans);
    142             else printf("-1
    ");
    143         }
    144     }
    145     return 0;
    146 }
  • 相关阅读:
    GSM Arena 魅族mx四核评测个人翻译
    Oracle Exists用法|转|
    NC公有协同的实现原理|同13的QQ||更新总部往来协同|
    NC客商bd_custbank不可修改账号、名称但可修改默认银行并更新分子公司trigger
    试玩了plsql中test窗口declare声明变量|lpad函数||plsql sql command test window区别|
    使用windows live writer测试
    用友写insert on bd_custbank 触发器和自动更新单位名称2in1
    oracle触发器select into和cursor用法的区别
    |转|oracle中prior的用法,connect by prior,树形目录
    客商增加自动增加银行账户|搞定!||更新使用游标course写法|
  • 原文地址:https://www.cnblogs.com/KonjakJuruo/p/5748643.html
Copyright © 2020-2023  润新知