真正的危机不是机器人像人一样思考,而是人像机器一样思考。 ——凉宫春日的忧郁

[HZOI 2016]tree—增强版

[HZOI 2016]tree—增强版

注意事项

为了体现增强版,题目限制和数据范围有所增强:

时间限制:1.5s

内存限制:128MB

对于15% 的数据,1<=N,Q<=1000.

对于35% 的数据,1<=N,Q<=10000.

对于50% 的数据,1<=N,Q<=100000,且数据均为官方数据.

对于100% 的数据,1<=N,Q<=1000000.

请注意常数因子对于程序运行的影响。

解题报告

原题数据水到不行= =

直接找父节点都能上榜= =

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 inline int read(){
 6     int sum(0);
 7     char ch(getchar());
 8     for(;ch<'0'||ch>'9';ch=getchar());
 9     for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar());
10     return sum;
11 }
12 struct edge{
13     int e;
14     edge *n;
15     edge():e(0),n(NULL){}
16 }a[200005],*pre[100005];
17 int tot;
18 inline void insert(int s,int e){
19     a[++tot].e=e;
20     a[tot].n=pre[s];
21     pre[s]=&a[tot];
22 }
23 int n,q;
24 char op[2];
25 bool bj[100005];
26 int fa[100005];
27 inline void dfs(int u){
28     for(edge *i=pre[u];i;i=i->n){
29         int e(i->e);
30         if(e!=fa[u]){
31             fa[e]=u;
32             dfs(e);
33         }
34     }
35 }
36 inline int query(int u){
37     while(!bj[u])
38         u=fa[u];
39     return u;
40 }
41 inline int gg(){
42     freopen("heoi2016_tree.in","r",stdin);
43     freopen("heoi2016_tree.out","w",stdout);
44     memset(pre,NULL,sizeof(pre));
45     n=read(),q=read();
46     bj[1]=1;
47     for(int i=1;i<n;++i){
48         int x(read()),y(read());
49         insert(x,y),insert(y,x);
50     }
51     dfs(1);
52     while(q--){
53         scanf("%s",op);
54         int x(read());
55         if(op[0]=='Q')
56             printf("%d\n",query(x));
57         else
58             bj[x]=1;
59     }
60     return 0;
61 }
62 int K(gg());
63 int main(){;}
View Code

然而加强版数据真的不是闹着玩的= =

首先我们看,它是一个不断往上爬,直到爬到第一个有标记的点或者是根节点时才停止的过程,那么我们很容易想到树剖,从当前节点往上爬就好了

同时我们注意到,题目要求找离当前节点最近的被标记的祖先,所以我们只要去找深度最深的被标记的祖先即可,而由树链剖分中$dfs$序的性质可知,在同一条链上越深的节点,它的时间戳就越大,那么我们显然可以维护一颗最大值的线段树,假如该点被标记,就把它的时间戳加入线段树

剩下的就很好实现了

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<cstdlib>
  5 using namespace std;
  6 inline int read(){
  7     int sum=0;
  8     char ch=getchar();
  9     for(;ch<'0'||ch>'9';ch=getchar());
 10     for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar());
 11     return sum;
 12 }
 13 struct edge{
 14     int e,n;
 15 }a[1000005];
 16 int pre[1000005];
 17 int tot;
 18 inline void insert(int s,int e){
 19     a[++tot].e=e;
 20     a[tot].n=pre[s];
 21     pre[s]=tot;
 22 }
 23 int dep[1000005],fa[1000005],son[1000005],size[1000005];
 24 inline void dfs1(int u){
 25     size[u]=1,son[u]=0;
 26     for(int i=pre[u];i!=-1;i=a[i].n){
 27         int e=a[i].e;
 28         if(e!=fa[u]){
 29             fa[e]=u;
 30             dep[e]=dep[u]+1;
 31             dfs1(e);
 32             size[u]+=size[e];
 33             if(size[e]>size[son[u]])
 34                 son[u]=e;
 35         }
 36     }
 37 }
 38 int cnt;
 39 int top[1000005],id[1000005],pos[1000005];
 40 inline void dfs2(int u,int rt){
 41     top[u]=rt;
 42     id[u]=++cnt;
 43     pos[cnt]=u;
 44     if(son[u])
 45         dfs2(son[u],rt);
 46     else
 47         return;
 48     for(int i=pre[u];i!=-1;i=a[i].n){
 49         int e=a[i].e;
 50         if(e!=fa[u]&&e!=son[u])
 51             dfs2(e,e);
 52     }
 53 }
 54 int mx[4000005];
 55 inline void pushup(int i){
 56     mx[i]=max(mx[i<<1],mx[i<<1|1]);
 57 }
 58 inline void update(int pos,int l,int r,int i){
 59     if(l==r){
 60         mx[i]=pos;
 61         return;
 62     }
 63     int mid=l+r>>1;
 64     if(pos<=mid)
 65         update(pos,l,mid,i<<1);
 66     else
 67         update(pos,mid+1,r,i<<1|1);
 68     pushup(i);
 69 }
 70 inline int query(int ll,int rr,int l,int r,int i){
 71     if(ll<=l&&r<=rr)
 72         return mx[i];
 73     int mid=l+r>>1,ret=0;
 74     if(ll<=mid)
 75         ret=max(query(ll,rr,l,mid,i<<1),ret);
 76     if(mid<rr)
 77         ret=max(query(ll,rr,mid+1,r,i<<1|1),ret);
 78     return ret;
 79 }
 80 int n,q;
 81 char op[2];
 82 inline int ask(int x){
 83     int ret(1);
 84     while(x){
 85         int tmp=query(id[top[x]],id[x],1,n,1);
 86         if(tmp)
 87             ret=dep[ret]>dep[pos[tmp]]?ret:pos[tmp];
 88         x=fa[top[x]];
 89     }
 90     return ret;
 91 }
 92 int main(){
 93     int __size__ = 50 << 20;
 94     char *__p__ = (char*)malloc(__size__) + __size__;
 95     __asm__("movl %0, %%esp\n" :: "r"(__p__));
 96     freopen("tree++.in","r",stdin);
 97     freopen("tree++.out","w",stdout);
 98     memset(pre,-1,sizeof(pre));
 99     n=read(),q=read();
100     for(int i=1;i<n;++i){
101         int x=read(),y=read();
102         insert(x,y);
103     }
104     dfs1(1);
105     dfs2(1,1);
106     int x;
107     update(id[1],1,n,1);
108     for(int i=0;i<q;++i){
109         scanf("%s",op);
110         x=read();
111         if(op[0]=='Q')
112             printf("%d\n",ask(x));
113         else
114             update(id[x],1,n,1);
115     }
116     return 0;
117 }
View Code

 

posted @ 2017-08-23 15:40  Hzoi_Mafia  阅读(172)  评论(0编辑  收藏  举报
我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。 ——死神