zoukankan      html  css  js  c++  java
  • [BZOJ2588] Count on a tree

    Description

    给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。

    Input

    第一行两个整数N,M。
    第二行有N个整数,其中第i个整数表示点i的权值。
    后面N-1行每行两个整数(x,y),表示点x到点y有一条边。
    最后M行每行两个整数(u,v,k),表示一组询问。

    Output

    M行,表示每个询问的答案。最后一个询问不输出换行符

    Sample Input

    8 5
    105 2 9 3 8 5 7 7
    1 2
    1 3
    1 4
    3 5
    3 6
    3 7
    4 8
    2 5 1
    0 5 2
    10 5 3
    11 5 4
    110 8 2

    Sample Output

    2
    8
    9
    105
    7

    HINT

    HINT:

    N,M<=100000

    暴力自重。。。

    Source

    鸣谢seter

    思路

    树链剖分+主席树,然后用一棵线段树辅助查询。

    没注意判断,有一些查询集里多加了root节点;

    然后R了好久;

    然后,多谢大佬提醒,给区间边界加了特判,然后就能在答案错误时输出了;

    然后T掉了。。。

    没搞清楚主席树,主席树是对于某一个节点扩展出新树,所以树状数据也可以直接按父子关系存储;

    然后用LCA get到所需的树链的数据,查询即可;

    然后。。。学了一下unique()去重函数;

    代码实现

     1 #include<cstdio>
     2 #include<cstring>
     3 const int maxn=1e5+10;
     4 const int inf=0x7fffffff;
     5 inline int min_(int x,int y){return x<y?x:y;}
     6 inline int max_(int x,int y){return x>y?x:y;}
     7 inline void swap_(int&x,int&y){x^=y,y^=x,x^=y;}
     8 int h[maxn],hs,et[maxn<<1],en[maxn<<1];
     9 int p[maxn],pf[maxn],pd[maxn],pt[maxn],pp[maxn],pps,psz[maxn],pws[maxn];
    10 int s[maxn];
    11 int rt[maxn],ts,t[maxn<<5],tl[maxn<<5],tr[maxn<<5];
    12 int nrt,nts,nt[maxn<<4],ntl[maxn<<4],ntr[maxn<<4];
    13 int n,m;
    14 int a,b,c,ans;
    15 void dfs1(int k,int f,int d){
    16     pf[k]=f,pd[k]=d,psz[k]=1;
    17     for(int i=h[k];i;i=en[i])
    18     if(et[i]!=f){
    19         dfs1(et[i],k,d+1);
    20         psz[k]+=psz[et[i]];
    21         if(psz[et[i]]>psz[pws[k]]) pws[k]=et[i];
    22     }
    23 }
    24 void dfs2(int k,int t){
    25     s[++pps]=p[k],pp[k]=pps,pt[k]=t;
    26     if(pws[k]) dfs2(pws[k],t);
    27     for(int i=h[k];i;i=en[i])
    28     if(et[i]!=pf[k]&&et[i]!=pws[k])
    29     dfs2(et[i],et[i]);
    30 }
    31 void build(int pre,int&suc,int l,int r,int v){
    32     suc=++ts;
    33     if(l==r){t[suc]=t[pre]+1;return;}
    34     int mid=0ll+l+r>>1;
    35     if(v<=mid) tr[suc]=tr[pre],build(tl[pre],tl[suc],l,mid,v);
    36     else tl[suc]=tl[pre],build(tr[pre],tr[suc],mid+1,r,v);
    37     t[suc]=t[tl[suc]]+t[tr[suc]];
    38 }
    39 void move(int pre,int suc,int&k,int l,int r){
    40     if(!k) k=++nts;
    41     nt[k]+=t[suc]-t[pre];
    42     if(l==r) return;
    43     int mid=0ll+l+r>>1;
    44     if(t[tl[suc]]-t[tl[pre]]) move(tl[pre],tl[suc],ntl[k],l,mid);
    45     if(t[tr[suc]]-t[tr[pre]]) move(tr[pre],tr[suc],ntr[k],mid+1,r);
    46 }
    47 int search(int k,int l,int r,int v){
    48     if(l==r) return l;
    49     int mid=0ll+l+r>>1,ls=k<<1,rs=ls|1;
    50     if(v<=nt[ntl[k]]) return search(ntl[k],l,mid,v);
    51     else return search(ntr[k],mid+1,r,v-nt[ntl[k]]);
    52 }
    53 int main(){
    54     scanf("%d%d",&n,&m);
    55     for(int i=1;i<=n;i++) scanf("%d",&p[i]);
    56     for(int i=1;i<n;i++){
    57         scanf("%d%d",&a,&b);
    58         ++hs,et[hs]=b,en[hs]=h[a],h[a]=hs;
    59         ++hs,et[hs]=a,en[hs]=h[b],h[b]=hs;
    60     }
    61     dfs1(1,1,1);
    62     dfs2(1,1);
    63     for(int i=1;i<=n;i++) build(rt[i-1],rt[i],1,inf,s[i]);
    64     for(int i=1;i<=m;i++){
    65         scanf("%d%d%d",&a,&b,&c);a^=ans;
    66         while(pt[a]!=pt[b]){
    67             if(pd[pt[a]]<pd[pt[b]]) swap_(a,b);
    68             move(rt[pp[pt[a]]-1],rt[pp[a]],nrt,1,inf);
    69             a=pf[pt[a]];
    70         }
    71         if(pp[a]>pp[b]) swap_(a,b);
    72         move(rt[pp[a]-1],rt[pp[b]],nrt,1,inf);
    73         ans=search(nrt,1,inf,c);
    74         printf("%d",ans);
    75         nrt=nts=0;
    76         memset(nt,0,sizeof(nt));
    77         memset(ntl,0,sizeof(ntl));
    78         memset(ntr,0,sizeof(ntr));
    79         if(i!=m) putchar('
    ');
    80     }
    81     return 0;
    82 }
    T掉了。
     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 const int maxn=1e5+10;
     5 int n,m;
     6 int a,b,c,aa,bb,ans,inf;
     7 int h[maxn],hs,et[maxn<<1],en[maxn<<1];
     8 int p[maxn],pf[maxn][32],pd[maxn];
     9 int rt[maxn],ts,t[maxn<<5],tl[maxn<<5],tr[maxn<<5];
    10 int s[maxn],hash[maxn];
    11 void build(int pre,int&suc,int l,int r,int v){
    12     if(!suc) suc=++ts;
    13     t[suc]=t[pre]+1;
    14     if(l==r) return;
    15     int mid=0ll+l+r>>1;
    16     if(v<=hash[mid]) tr[suc]=tr[pre],build(tl[pre],tl[suc],l,mid,v);
    17     else tl[suc]=tl[pre],build(tr[pre],tr[suc],mid+1,r,v);
    18 }
    19 void dfs(int k,int f,int d){
    20     pd[k]=d,s[d]=k;
    21     build(rt[f],rt[k],1,inf,p[k]);
    22     for(int i=1,j=0;d-i>0;i<<=1,j++) pf[k][j]=s[d-i];
    23     for(int i=h[k];i;i=en[i])
    24     if(et[i]!=f) dfs(et[i],k,d+1);
    25 }
    26 int search(int k1,int k2,int k3,int k4,int l,int r,int v){
    27     if(l==r) return l;
    28     int mid=0ll+l+r>>1,w=t[tl[k1]]+t[tl[k2]]-t[tl[k3]]-t[tl[k4]];
    29     if(v<=w) return search(tl[k1],tl[k2],tl[k3],tl[k4],l,mid,v);
    30     else return search(tr[k1],tr[k2],tr[k3],tr[k4],mid+1,r,v-w);
    31 }
    32 int main(){
    33     scanf("%d%d",&n,&m);
    34     for(int i=1;i<=n;i++) scanf("%d",&p[i]),hash[i]=p[i];
    35     sort(hash+1,hash+n+1);
    36     inf=unique(hash,hash+n+1)-hash-1;
    37     for(int i=1;i<n;i++){
    38         scanf("%d%d",&a,&b);
    39         ++hs,et[hs]=b,en[hs]=h[a],h[a]=hs;
    40         ++hs,et[hs]=a,en[hs]=h[b],h[b]=hs;
    41     }
    42     dfs(1,0,1);
    43     while(m--){
    44         scanf("%d%d%d",&a,&b,&c);
    45         a^=ans,aa=a,bb=b;
    46         if(a<0||a>n) return 0;
    47         while(a!=b){
    48             if(pd[a]==pd[b]) for(int j=0;;j++) if(pf[a][j+1]==pf[b][j+1]){a=pf[a][j],b=pf[b][j];break;}
    49             if(pd[a]>pd[b]) for(int j=0;;j++) if(pd[pf[a][j+1]]<pd[b]){a=pf[a][j];break;}
    50             if(pd[a]<pd[b]) for(int j=0;;j++) if(pd[pf[b][j+1]]<pd[a]){b=pf[b][j];break;}
    51         }
    52         ans=hash[search(rt[aa],rt[bb],rt[a],rt[pf[a][0]],1,inf,c)];
    53         printf("%d",ans);
    54         if(m) putchar('
    ');
    55     }
    56     return 0;
    57 }

     顺便,SPOJ这道题因为太水已经被删除了。。。我好弱。

    顺便,对拍用的maker. by:http://blog.csdn.net/baidu_23081367/article/details/53036792

     1     #include <cstdio>  
     2     #include <cstring>  
     3     #include <vector>  
     4     #include <ctime>  
     5     #include <iostream>  
     6     #include <cstdlib>  
     7     using namespace std;  
     8       
     9     int main()  
    10     {  
    11         srand(time(0));  
    12         int T=1;//改数据组数  
    13         while (T--)  
    14         {  
    15             int n = rand() % 100 + 1; //这里改树的大小  
    16             int m = 100;  //修改询问次数  
    17             cout<<n<<" "<<m<<endl;  
    18             for (int i = 1; i <= n; ++ i)  
    19                 cout << rand()%100+1<<" ";cout<<endl; //修改每个读入的数字大小  
    20             for (int i = 2; i <= n; ++ i)  
    21             {  
    22                 int a = i, b = rand()%(i-1)+1;  
    23                 cout << a <<" " << b<<endl;  
    24             }  
    25             while ( m -- )  
    26             {  
    27                 int a = rand()%n+1;  
    28                 int b = rand()%n+1;  
    29                 int l = abs(a-b)+1;  
    30                 cout<<a<<" "<<b<<" "<<rand()%l+1<<endl;  
    31             }  
    32         }  
    33         return 0;  
    34     }  
  • 相关阅读:
    DS博客作业08--课程总结
    DS博客作业07-----查找
    DS博客作业06--图
    DS博客作业05--树
    DS博客作业08--课程总结
    DS博客作业07--查找
    DS博客作业06--图
    DS博客作业05--树
    DS博客作业03--栈和队列
    DS博客作业02--线性表
  • 原文地址:https://www.cnblogs.com/J-william/p/7029413.html
Copyright © 2011-2022 走看看