博客
关于我
P3899 [湖南集训]谈笑风生 主席树解决二维数点
阅读量:275 次
发布时间:2019-03-01

本文共 3322 字,大约阅读时间需要 11 分钟。

文章目录

题意:

在这里插入图片描述

思路:

由于 a , b a,b a,b都比 c c c厉害,那么 a , b a,b a,b一定是某个是某个的祖先。那么就分为两种情况了:

( 1 ) (1) (1) b b b a a a上面,约定 d e p t h [ 1 ] = 1 depth[1]=1 depth[1]=1,此时答案显然为 m i n ( d e p t h [ a ] − 1 , k ) ∗ ( s e [ a ] − 1 ) min(depth[a]-1,k)*(se[a]-1) min(depth[a]1,k)(se[a]1)
( 2 ) (2) (2) b b b a a a的下下面,这个时候就不是那么容易搞了,问题转化成我们要求 a a a这个子树中 d e p t h depth depth范围在 [ d e p t h [ a ] + 1 , d e p t h [ a ] + k ] [depth[a]+1,depth[a]+k] [depth[a]+1,depth[a]+k]内的所有点的 s e [ i ] − 1 se[i]-1 se[i]1,先考虑暴力怎么写呢?显然我们可以暴力对这颗子树的深度建线段树,这样就变成了区间查询的问题了。而这样复杂度是肯定不行的,所以我们考虑建可持久化线段树,根据树的 d f s dfs dfs序建主席树,以节点深度为下标,那么查询就变成了 q u e r y ( r o o t [ d f n [ p ] ] , r o o t [ d f n [ p ] + s e [ p ] − 1 ] , 1 , n , d e p t h [ p ] + 1 , m i n ( d e p t h [ p ] + k , n ) ) query(root[dfn[p]],root[dfn[p]+se[p]-1],1,n,depth[p]+1,min(depth[p]+k,n)) query(root[dfn[p]],root[dfn[p]+se[p]1],1,n,depth[p]+1,min(depth[p]+k,n)),再加上 ( 1 ) (1) (1)的答案即可。

我们还可以将其转换成二维数点的问题。

通过以上分析不难发现我们要找的点就是
深度范围是 [ d e p t h [ p ] + 1 , d e p t h [ p ] + k ] [depth[p]+1,depth[p]+k] [depth[p]+1,depth[p]+k] d f s dfs dfs序范围是 [ d f n [ p ] , d f n [ p ] + s e [ p ] − 1 ] [dfn[p],dfn[p]+se[p]-1] [dfn[p],dfn[p]+se[p]1],那么我们以深度建立 x x x轴,以 d f s dfs dfs序建立 y y y轴,让后统计就好啦。

主席树 O ( n l o g n ) O(nlogn) O(nlogn)

//#pragma GCC optimize(2)#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define X first#define Y second#define L (u<<1)#define R (u<<1|1)#define pb push_back#define mk make_pair#define Mid (tr[u].l+tr[u].r>>1)#define Len(u) (tr[u].r-tr[u].l+1)#define random(a,b) ((a)+rand()%((b)-(a)+1))#define db puts("---")using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL;typedef unsigned long long ULL;typedef pair
PII;const int N=1000010,mod=1e9+7,INF=0x3f3f3f3f;const double eps=1e-6;int n,m;int root[N],tot,idx;int dfn[N],se[N],depth[N];vector
v[N];struct Node{ int l,r; LL sum;}tr[N*40];void insert(int p,int &q,int l,int r,int pos,int x){ q=++tot; tr[q]=tr[p]; tr[q].sum+=x; if(l==r) return; int mid=l+r>>1; if(pos<=mid) insert(tr[p].l,tr[q].l,l,mid,pos,x); else insert(tr[p].r,tr[q].r,mid+1,r,pos,x);}LL query(int p,int q,int l,int r,int ql,int qr){ if(l>=ql&&r<=qr) return tr[q].sum-tr[p].sum; LL ans=0; int mid=l+r>>1; if(ql<=mid) ans+=query(tr[p].l,tr[q].l,l,mid,ql,qr); if(qr>mid) ans+=query(tr[p].r,tr[q].r,mid+1,r,ql,qr); return ans;}void dfs1(int u,int fa){ se[u]=1; dfn[u]=++idx; depth[u]=depth[fa]+1; for(auto x:v[u]) if(x!=fa) dfs1(x,u),se[u]+=se[x];}void dfs2(int u,int fa){ insert(root[dfn[u]-1],root[dfn[u]],1,n,depth[u],se[u]-1); for(auto x:v[u]) if(x!=fa) dfs2(x,u);}int main(){ // ios::sync_with_stdio(false);// cin.tie(0); scanf("%d%d",&n,&m); for(int i=1;i<=n-1;i++) { int a,b; scanf("%d%d",&a,&b); v[a].pb(b); v[b].pb(a); } dfs1(1,0); dfs2(1,0); while(m--) { int p,k; scanf("%d%d",&p,&k); LL ans=1ll*min(depth[p]-1,k)*(se[p]-1); ans+=query(root[dfn[p]],root[dfn[p]+se[p]-1],1,n,depth[p]+1,min(depth[p]+k,n)); printf("%lld\n",ans); } return 0;}/**/

转载地址:http://xvlx.baihongyu.com/

你可能感兴趣的文章
msbuild发布web应用程序
查看>>
MSB与LSB
查看>>
MSCRM调用外部JS文件
查看>>
MSCRM调用外部JS文件
查看>>
MSEdgeDriver (Chromium) 不适用于版本 >= 79.0.313 (Canary)
查看>>
MsEdgeTTS开源项目使用教程
查看>>
msf
查看>>
MSP430F149学习之路——SPI
查看>>
msp430入门编程45
查看>>
MSSQL数据库查询优化(一)
查看>>
MSSQL数据库迁移到Oracle(二)
查看>>
MSSQL日期格式转换函数(使用CONVERT)
查看>>
MSTP多生成树协议(第二课)
查看>>
MSTP是什么?有哪些专有名词?
查看>>
Mstsc 远程桌面链接 And 网络映射
查看>>
Myeclipse常用快捷键
查看>>
MyEclipse更改项目名web发布名字不改问题
查看>>
MyEclipse用(JDBC)连接SQL出现的问题~
查看>>
mt-datetime-picker type="date" 时间格式 bug
查看>>
myeclipse的新建severlet不见解决方法
查看>>