【BZOJ】【2588】COT(Count On a Tree)

可持久化线段树



  maya……树么……转化成序列……所以就写了个树链剖分……然后每个点保存的是从它到根的可持久化线段树

  然后就像序列一样查询……注意是多个左端点和多个右端点,处理方法类似BZOJ 1901

  然后rausen(Orz!!!)粗来跟我说:你直接减去lca和fa[lca]不就好啦~搞树剖还多一个log……

  我恍然大悟!然后两个都交了一下,事实证明:我链剖写的还行,LCA写的太丑……速度反而是多一个log的链剖快QAQ(另:因为边少我就偷懒没写边表,直接vector水过)

链剖:

  1 /**************************************************************
  2     Problem: 2588
  3     User: ProgrammingApe
  4     Language: C++
  5     Result: Accepted
  6     Time:3768 ms
  7     Memory:47652 kb
  8 ****************************************************************/
  9
 10 //BZOJ 2588
 11 #include<vector>
 12 #include<cstdio>
 13 #include<cstring>
 14 #include<iostream>
 15 #include<algorithm>
 16 #define rep(i,n) for(int i=0;i<n;++i)
 17 #define F(i,j,n) for(int i=j;i<=n;++i)
 18 #define D(i,j,n) for(int i=j;i>=n;--i)
 19 #define pb push_back
 20 using namespace std;
 21 inline int getint(){
 22     int v=0,sign=1; char ch=getchar();
 23     while(!isdigit(ch)) {if(ch==‘-‘) sign=-1; ch=getchar();}
 24     while(isdigit(ch))  {v=v*10+ch-‘0‘; ch=getchar();}
 25     return v*sign;
 26 }
 27 const int N=1e5+10,INF=~0u>>2;
 28 /*******************template********************/
 29 struct tree{
 30     int cnt,l,r;
 31 }t[N*30];
 32 int root[N],cnt,num;
 33 int lc,rc,ln[N],rn[N];
 34 #define mid (l+r>>1)
 35 void update(int &o,int l,int r,int pos){
 36     t[++cnt]=t[o]; o=cnt; t[o].cnt++;
 37     if (l==r) return;
 38     if (pos<=mid) update(t[o].l,l,mid,pos);
 39     else update(t[o].r,mid+1,r,pos);
 40 }
 41 int query_t(int rank){
 42     int l=1,r=num;
 43     int tl=0,tr=0;
 44     while(l!=r){
 45         tl=tr=0;
 46         F(i,1,lc) tl+=t[t[ln[i]].l].cnt;
 47         F(i,1,rc) tr+=t[t[rn[i]].l].cnt;
 48         if (tr-tl>=rank){
 49             F(i,1,lc) ln[i]=t[ln[i]].l;
 50             F(i,1,rc) rn[i]=t[rn[i]].l;
 51             r=mid;
 52         }else{
 53             F(i,1,lc) ln[i]=t[ln[i]].r;
 54             F(i,1,rc) rn[i]=t[rn[i]].r;
 55             l=mid+1; rank-=tr-tl;
 56         }
 57     }
 58     return l;
 59 }
 60 /*****************可持久化线段树 ***************/
 61 vector<int>G[N];
 62 int top[N],fa[N],son[N],dep[N],tot,size[N],a[N],b[N],n,m,lastans;
 63 bool vis[N];
 64 void dfs(int x,int f,int d){
 65     vis[x]=1;
 66     fa[x]=f; dep[x]=d; size[x]=1; son[x]=0;
 67     int maxsize=0;
 68     rep(i,G[x].size()){
 69         int to=G[x][i];
 70         if (vis[to]) continue;
 71         dfs(to,x,d+1);
 72         size[x]+=size[to];
 73         if (size[to]>maxsize) maxsize=size[to],son[x]=to;
 74     }
 75 }
 76 void connect(int x,int f){
 77     vis[x]=1;
 78     root[x]=root[fa[x]];
 79     update(root[x],1,num,a[x]);
 80 //  root[x]=++tot;
 81     top[x]=f;
 82     if (son[x]) connect(son[x],f);
 83     rep(i,G[x].size()){
 84         int to=G[x][i];
 85         if (!vis[to]) connect(to,to);
 86     }
 87 }
 88 void query(int x,int y,int k){
 89     lc=rc=0;
 90     while(top[x]!=top[y]){
 91         if (dep[top[x]]<dep[top[y]]) swap(x,y);
 92         ln[++lc]=root[fa[top[x]]]; rn[++rc]=root[x];
 93         x=fa[top[x]];
 94     }
 95     if (dep[x]>dep[y]) swap(x,y);
 96     ln[++lc]=root[fa[x]]; rn[++rc]=root[y];
 97     printf("%d",lastans=b[query_t(k)]);
 98 }
 99 /**********************链剖*********************/
100 int main(){
101 //  freopen("input.txt","r",stdin);
102     n=getint(); m=getint();
103     F(i,1,n) b[i]=a[i]=getint();
104     sort(b+1,b+n+1);
105     num=unique(b+1,b+n+1)-b-1;
106     F(i,1,n) a[i]=lower_bound(b+1,b+num+1,a[i])-b;
107
108     int x,y,k;
109     F(i,2,n){
110         x=getint(); y=getint();
111         G[x].pb(y); G[y].pb(x);
112     }
113     dfs(1,0,1);
114     memset(vis,0,sizeof vis);
115     connect(1,1);
116
117     F(i,1,m){
118         x=lastans^getint(); y=getint(); k=getint();
119         query(x,y,k);
120         if (i!=m) puts("");
121     }
122     return 0;
123 }

倍增LCA:

  1 /**************************************************************
  2     Problem: 2588
  3     User: Tunix
  4     Language: C++
  5     Result: Accepted
  6     Time:4520 ms
  7     Memory:53024 kb
  8 ****************************************************************/
  9
 10 //BZOJ 2588
 11 #include<vector>
 12 #include<cstdio>
 13 #include<cstring>
 14 #include<iostream>
 15 #include<algorithm>
 16 #define rep(i,n) for(int i=0;i<n;++i)
 17 #define F(i,j,n) for(int i=j;i<=n;++i)
 18 #define D(i,j,n) for(int i=j;i>=n;--i)
 19 #define pb push_back
 20 using namespace std;
 21 inline int getint(){
 22     int v=0,sign=1; char ch=getchar();
 23     while(!isdigit(ch)) {if(ch==‘-‘) sign=-1; ch=getchar();}
 24     while(isdigit(ch))  {v=v*10+ch-‘0‘; ch=getchar();}
 25     return v*sign;
 26 }
 27 const int N=1e5+10,INF=~0u>>2;
 28 /*******************template********************/
 29 struct tree{
 30     int cnt,l,r;
 31 }t[N*30];
 32 int root[N],cnt,num;
 33 int lc,rc,ln[N],rn[N];
 34 #define mid (l+r>>1)
 35 void update(int &o,int l,int r,int pos){
 36     t[++cnt]=t[o]; o=cnt; t[o].cnt++;
 37     if (l==r) return;
 38     if (pos<=mid) update(t[o].l,l,mid,pos);
 39     else update(t[o].r,mid+1,r,pos);
 40 }
 41 int query_t(int rank){
 42     int l=1,r=num;
 43     int tl=0,tr=0;
 44     while(l!=r){
 45         tl=tr=0;
 46         F(i,1,lc) tl+=t[t[ln[i]].l].cnt;
 47         F(i,1,rc) tr+=t[t[rn[i]].l].cnt;
 48         if (tr-tl>=rank){
 49             F(i,1,lc) ln[i]=t[ln[i]].l;
 50             F(i,1,rc) rn[i]=t[rn[i]].l;
 51             r=mid;
 52         }else{
 53             F(i,1,lc) ln[i]=t[ln[i]].r;
 54             F(i,1,rc) rn[i]=t[rn[i]].r;
 55             l=mid+1; rank-=tr-tl;
 56         }
 57     }
 58     return l;
 59 }
 60 /*****************可持久化线段树 ***************/
 61 vector<int>G[N];
 62 int fa[N][18],dep[N],a[N],b[N],n,m,lastans;
 63 void dfs(int x){
 64     F(i,1,17)
 65         if (dep[x]>=(1<<i)) fa[x][i]=fa[fa[x][i-1]][i-1];
 66         else break;
 67     root[x]=root[fa[x][0]];
 68     update(root[x],1,num,a[x]);
 69     rep(i,G[x].size()){
 70         int to=G[x][i];
 71         if (to==fa[x][0]) continue;
 72         fa[to][0]=x; dep[to]=dep[x]+1;
 73         dfs(to);
 74     }
 75 }
 76 int LCA(int x,int y){
 77     if (dep[x]<dep[y]) swap(x,y);
 78     int t=dep[x]-dep[y];
 79     for(int i=0;(1<<i)<=t;i++)
 80         if(t&(1<<i)) x=fa[x][i];
 81     D(i,17,0)
 82         if(fa[x][i]!=fa[y][i])
 83             x=fa[x][i],y=fa[y][i];
 84     if (x==y) return x;
 85     return fa[x][0];
 86 }
 87 void query(int x,int y,int k){
 88     lc=rc=0;
 89     int lca=LCA(x,y);
 90     ln[++lc]=root[lca]; ln[++lc]=root[fa[lca][0]];
 91     rn[++rc]=root[x]; rn[++rc]=root[y];
 92     printf("%d",lastans=b[query_t(k)]);
 93 }
 94 /**********************LCA*********************/
 95 int main(){
 96     n=getint(); m=getint();
 97     F(i,1,n) b[i]=a[i]=getint();
 98     sort(b+1,b+n+1);
 99     num=unique(b+1,b+n+1)-b-1;
100     F(i,1,n) a[i]=lower_bound(b+1,b+num+1,a[i])-b;
101
102     int x,y,k;
103     F(i,2,n){
104         x=getint(); y=getint();
105         G[x].pb(y); G[y].pb(x);
106     }
107     dfs(1);
108
109     F(i,1,m){
110         x=lastans^getint(); y=getint(); k=getint();
111         query(x,y,k);
112         if (i!=m) puts("");
113     }
114     return 0;
115 }

时间: 2024-11-12 21:03:53

【BZOJ】【2588】COT(Count On a Tree)的相关文章

P2433 - 【BZOJ 3262三维偏序】陌上花开------三维偏序

P2433 - [BZOJ 3262三维偏序]陌上花开 Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量. 定义一朵花A比另一朵花B要美丽,当且仅当Sa>=Sb,Ca>=Cb,Ma>=Mb.显然,两朵花可能有同样的属性.需要统计出评出每个等级的花的数量. Input 第一行为N,K (1 <= N <= 100,000, 1 <= K <= 200,

【BZOJ1415】【NOI2005】聪聪和可可(动态规划,数学期望)

[BZOJ1415][NOI2005]聪聪和可可(动态规划,数学期望) 题面 BZOJ 题解 先预处理出当可可在某个点,聪聪在某个点时 聪聪会往哪里走 然后记忆化搜索一下就好了 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<set> #i

【BZOJ5248】【九省联考2018】一双木棋(搜索,哈希)

[BZOJ5248][九省联考2018]一双木棋(搜索,哈希) 题面 BZOJ Description 菲菲和牛牛在一块n行m列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手.棋局开始时,棋盘上没有任何棋子, 两人轮流在格子上落子,直到填满棋盘时结束.落子的规则是:一个格子可以落子当且仅当这个格子内没有棋子且 这个格子的左侧及上方的所有格子内都有棋子. 棋盘的每个格子上,都写有两个非负整数,从上到下第i行中从左到右第j列的格子上的两个整数记作Aij.Bij.在 游戏结束后,菲菲和牛牛会分别计算自己

【POJ 2482】 Stars in Your Window(线段树+离散化+扫描线)

[POJ 2482] Stars in Your Window(线段树+离散化+扫描线) Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11294   Accepted: 3091 Description Fleeting time does not blur my memory of you. Can it really be 4 years since I first saw you? I still remembe

【js】js访问剪切板(兼容各大浏览器)唯一解决方案ZeroClipboard.swf

需求描述: 通过JS实现将页面中的某个元素的数据复制到剪切板上. 需求分析: 要用JS实现最大的问题就是浏览器的兼容性问题了.而且最大的问题还是浏览器出于安全型的考虑,所以像chrome,Firefox等浏览器都不让访问. 解决方案: 最终的解决方案还是通过flash实现的,在网上搜索(关键字:js access clipboard)了一大堆的相关资料,但是这或许是唯一的解决方案了吧!真没想到,flash还是最终的解决方法.当有一天flash彻底被浏览器给抛弃了我想这又将是一大问题了.但是这个问

【转】Unity资源管理原理知识(干货不嫌长)

最近unity 当需要频繁创建一个物体对象时,怎样减少内存. 这里写下关于Unity3D对于内存的管理与优化. Unity3D 里有两种动态加载机制:一个是Resources.Load,另外一个通过AssetBundle,其实两者区别不大. Resources.Load就是从一个缺省打进程序包里的AssetBundle里加载资源,而一般AssetBundle文件需要你自己创建,运行时 动态加载,可以指定路径和来源的. 其实场景里所有静态的对象也有这么一个加载过程,只是Unity3D后台替你自动完

【BZOJ做题记录】07.07~?

在NOI一周前重开一个坑 最后更新时间:7.07 11:26 7.06 下午做的几道CQOI题: BZOJ1257: [CQOI2007]余数之和sum:把k mod i写成k-k/i*i然后分段求后面的部分就好了 BZOJ1258: [CQOI2007]三角形tri:在草稿纸上按照位置和边找一下规律就好了 BZOJ1260: [CQOI2007]涂色paint:简单的区间DP BZOJ1303: [CQOI2009]中位数图:小于中位数的改为-1大于的改为1,算一算前缀和然后哈希一下乘一乘就好

【译】提升树算法的介绍(Introduction to Boosted Trees)

[译]提升树算法的介绍(Introduction to Boosted Trees) 1. 有监督学习的要素 XGBoost 适用于有监督学习问题.在此类问题中,我们使用多特征的训练数据集 \(x_i\) 去预测一个目标变量 \(y_i\) .在专门学习树模型前,我们先回顾一下有监督学习的基本要素. Elements of Supervised Learning XGBoost is used for supervised learning problems, where we use the

【CodeChef】Querying on a Grid(分治,最短路)

[CodeChef]Querying on a Grid(分治,最短路) 题面 Vjudge CodeChef 题解 考虑分治处理这个问题,每次取一个\(mid\),对于\(mid\)上的三个点构建最短路径树(因为保证了最短路唯一所以是树). 如果两点之间的最短路径跨越了\(mid\),那么必定有\(dis[u]+dis[v]\)的和就是最短路径长度. 那么我们在分治过程中考虑每一个\(mid\),取其中\(dis[u]+dis[v]\)的最小值,这样子就很容易可以找到最短路径长度. 然后知道了