博客
关于我
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/

你可能感兴趣的文章
MySQL原理、设计与应用全面解析
查看>>
MySQL原理简介—1.SQL的执行流程
查看>>
MySQL参数调优详解
查看>>
mysql参考触发条件_MySQL 5.0-触发器(参考)_mysql
查看>>
MySQL及navicat for mysql中文乱码
查看>>
MySqL双机热备份(二)--MysqL主-主复制实现
查看>>
MySql各种查询
查看>>
mysql同主机下 复制一个数据库所有文件到另一个数据库
查看>>
mysql启动以后会自动关闭_驾照虽然是C1,一直是开自动挡的车,会不会以后就不会开手动了?...
查看>>
mysql启动和关闭外键约束的方法(FOREIGN_KEY_CHECKS)
查看>>
Mysql启动失败解决过程
查看>>
MySQL启动失败:Can't start server: Bind on TCP/IP port
查看>>
mysql启动报错
查看>>
mysql启动报错The server quit without updating PID file几种解决办法
查看>>
MySQL命令行登陆,远程登陆MySQL
查看>>
mysql命令:set sql_log_bin=on/off
查看>>
mySQL和Hive的区别
查看>>
MySQL和Java数据类型对应
查看>>
mysql和oorcale日期区间查询【含左右区间问题】
查看>>
MySQL和SQL入门
查看>>