hdu 4358 深搜时间戳+线段树更新

其实这道题真的告诉了我一个道理,那就是仔细看题,题目中明确说出了1就是所有子树的根结点。

我们可以想一想,现在每个结点代表着一段区间的询问,所以我们必须利用深搜的时间戳来找出所有结点所代表的区间。

前向星见图自然不可少。

更新区间的话,我们必须用离线处理,[i,j]这个区间代表着第i个数在这个区内出现k次的数的个数。

View Code
  1 #include<algorithm>
  2 #include<iostream>
  3 #include<string.h>
  4 #include<cstdio>
  5 #include<vector>
  6 #include<map>
  7 #include<stdlib.h>
  8 using std::sort;
  9 using std::vector;
 10 using std::map;
 11 const int N = 100111;
 12 map<int,int> q;
 13 vector<int> p[N];
 14 struct Edge
 15 {
 16        int e,next;
 17 }edge[N<<1];

 18 int head[N],weight[N],visit[N],Ti;
 19 struct Query
 20 {
 21      int l,r,id;
 22      bool operator <(const Query & tmp)const
 23      {
 24          return r<tmp.r;
 25      }
 26 }que[N];
 27 struct node
 28 {
 29      int l,r;
 30 }No[N];
 31 int cover[N<<2],num[N],ans[N];
 32 void dfs(int u)
 33 {
 34      No[u].l=Ti;
 35      num[Ti]=weight[u];
 36      for(int i=head[u];i!=-1;i=edge[i].next)
 37      {
 38          if(visit[edge[i].e]==0)
 39          {
 40              visit[u]=1;
 41              Ti++;
 42              dfs(edge[i].e);
 43          }
 44      }
 45      No[u].r=Ti;
 46 }
 47 void PushDown(int t)
 48 {
 49      if(cover[t])
 50      {
 51          int t1=t<<1,t2=t1|1;
 52          cover[t1]+=cover[t];
 53          cover[t2]+=cover[t];
 54          cover[t]=0;
 55      }
 56      return ;
 57 }
 58 void update(int t,int l,int r,int L,int R,int val)
 59 {
 60      if(L<=l&&r<=R)
 61      {
 62          cover[t]+=val;
 63          return ;
 64      }
 65      PushDown(t);
 66      int m=(r+l)>>1;
 67      if(L<=m)update(t<<1,l,m,L,R,val);
 68      if(R>m)update(t<<1|1,m+1,r,L,R,val);
 69 }
 70 int query(int t,int l,int r,int i)
 71 {
 72      if(l==r)return cover[t];
 73      PushDown(t);
 74      int m=(l+r)>>1;
 75      if(i<=m)return query(t<<1,l,m,i);
 76      else return query(t<<1|1,m+1,r,i);
 77 }
 78 int main()
 79 {
 80     int t;
 81     int n,k,u,v,Q,T=0;
 82     scanf("%d",&t);
 83     while(t--)
 84     {
 85           scanf("%d%d",&n,&k);
 86           q.clear();
 87           int pos=1;
 88           for(int i=1;i<=n;i++)
 89           {
 90               scanf("%d",&weight[i]);
 91               if(q[weight[i]]==0)q[weight[i]]=pos++;
 92               weight[i]=q[weight[i]];
 93               head[i]=-1,visit[i]=0;
 94           }
 95           int tope=0;
 96           for(int i=0;i<pos;i++)
 97               p[i].clear();
 98           for(int i=1;i<n;i++)
 99           {
100               scanf("%d%d",&u,&v);
101               edge[tope].e=v;
102               edge[tope].next=head[u];
103               head[u]=tope++;
104               edge[tope].e=u;
105               edge[tope].next=head[v];
106               head[v]=tope++;
107           }
108           visit[1]=Ti=1;
109           dfs(1);
110           scanf("%d",&Q);
111           for(int i=1;i<=Q;i++)
112           {
113               scanf("%d",&u);
114               que[i].l=No[u].l;
115               que[i].r=No[u].r;
116               que[i].id=i;
117           }
118           sort(que+1,que+Q+1);
119           memset(cover,0,sizeof(cover));
120           for(int i=1,j=1;i<=n;i++)
121           {
122               p[num[i]].push_back(i);
123               int Count=p[num[i]].size();
124               if(Count>k)
125               {
126                   update(1,1,n,1,p[num[i]][Count-k-1],-1);
127                   update(1,1,n,p[num[i]][Count-k-1]+1,p[num[i]][Count-k],1);
128               }
129               else
130                 if(Count==k)
131                    update(1,1,n,1,p[num[i]][Count-k],1);
132               while(i>=que[j].r)
133               {
134                   ans[que[j].id]=query(1,1,n,que[j].l);
135                   j++;
136                   if(j>Q)break;
137               }
138               if(j>Q)break;
139           }
140           if(T!=0)printf("\n");
141           printf("Case #%d:\n",++T);
142           for(int i=1;i<=Q;i++)
143               printf("%d\n",ans[i]);
144     }
145     return 0;
146 }

 

posted @ 2012-11-24 11:29  诺小J  阅读(345)  评论(0编辑  收藏  举报