Codechef Union on Tree
Codechef Union on Tree
https://www.codechef.com/problems/BTREE
简要题意:
- 给你一棵树,\(Q\)次询问,每次给出一个点集和每个点的\(r_i\),每个点可以覆盖距离小于等于\(r_i\)的点。
- 问有多少点会被覆盖。
分析:
- 建出虚树,然后我们做两边\(dp\)把所有点的\(r_i\)更新成从这个点能覆盖的最远距离或从其他点出来经过这个点后能够覆盖的最远距离。
- 这样做的好处是对于一条边\((x,y)\),一定存在一个点\(z\),使得\(y\)更新\(z\)比\(x\)优。
- 于是可以计算答案,令\(F(x,d)\)为和\(x\)距离小于等于\(d\)的点数。
- 答案等于\(\sum\limits_iF(i,r_i)-\sum\limits_{x,y,p\in x,p\in y}1\)。 前面那个直接求就行了。
- 后面那个相当于找到这个\(z\),设\(x\)是\(y\)的祖先,有多个点在\(z\)上边被\(y\)包含,有多少点在\(z\)下边被\(x\)包含。
- 由于\(r_x-(dep_z-dep_x)=r_y-(dep_y-dep_z)\),可以确定\(z\)的位置,同时可以发现所求的点向上下延伸的长度是相等的,于是相当于求\(F(z,r_x-(dep_z-dep_x))\) 。
- 求\(F\)可以用动态点分治。
- 还有一个问题,可能不存在\(z\)这个点,可能在边上,我们一开始把边也当成点就好了。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <vector>
using namespace std;
#define N 100050
char buf[100000],*p1,*p2;
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
inline int rd() {int x=0;char c=nc(); while(c<48)c=nc();while(c>47)x=((x+(x<<2))<<1)+(c^48),c=nc(); return x;}
#define db(x) cerr<<#x<<" = "<<x<<endl
int head[N],to[N<<1],nxt[N<<1],cnt,n,m,ff[N],lm;
int siz[N],fk[N],tot,root,dep[N],fa[N][20],dis[N][20],used[N],ans;
int sz[N],son[N],d[N],f[N],top[N],dfn[N],idf[N];
int p[N],r[N],S[N],tp,vis[N];
vector<int>V[N][2];
inline void add(int u,int v) {to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;}
void gr(int x,int y) {
int i; siz[x]=1; fk[x]=0;
for(i=head[x];i;i=nxt[i]) if(to[i]!=y&&!used[to[i]]) {
gr(to[i],x); siz[x]+=siz[to[i]]; fk[x]=max(fk[x],siz[to[i]]);
}
fk[x]=max(fk[x],tot-siz[x]); if(fk[x]<fk[root]) root=x;
}
void gd(int x,int y,int rt,int d) {
sz[rt]+=(x<=n); V[rt][0][d]+=(x<=n); V[rt][1][dis[x][dep[x]]]+=(x<=n);
fa[x][++dep[x]]=rt; dis[x][dep[x]]=d; int i;
for(i=head[x];i;i=nxt[i]) if(to[i]!=y&&!used[to[i]]) {
gd(to[i],x,rt,d+1);
}
}
void solve(int x) {
int i,al=tot;
used[x]=1; V[x][0].resize(al+2),V[x][1].resize(al+2); gd(x,0,x,0);
for(i=1;i<al+2;i++) V[x][0][i]+=V[x][0][i-1],V[x][1][i]+=V[x][1][i-1];
for(i=head[x];i;i=nxt[i]) if(!used[to[i]]) {
tot=siz[to[i]]; if(tot>siz[x]) tot=al-siz[x]; root=0; gr(to[i],x); solve(root);
}
}
int query(int x,int o,int v) {if(!x) return 0; if(v>int(V[x][o].size())-1) return sz[x]; return V[x][o][v];}
int work(int x,int v) {if(v<0)return 0;int i,re=0; for(i=dep[x];i;i--) if(v>=dis[x][i]) re+=query(fa[x][i],0,v-dis[x][i])-query(fa[x][i+1],1,v-dis[x][i]); return re;}
void d1(int x,int y) {
f[x]=y,d[x]=d[y]+1,siz[x]=1;int i;
for(i=head[x];i;i=nxt[i]) if(to[i]!=y) {
d1(to[i],x),siz[x]+=siz[to[i]];
if(siz[to[i]]>siz[son[x]]) son[x]=to[i];
}
}
void d2(int x,int t) {
top[x]=t; dfn[x]=++dfn[0]; idf[dfn[0]]=x; if(son[x]) d2(son[x],t); int i;
for(i=head[x];i;i=nxt[i]) if(to[i]!=f[x]&&to[i]!=son[x]) d2(to[i],to[i]);
}
int lca(int x,int y) {for(;top[x]!=top[y];y=f[top[y]]) if(d[top[x]]>d[top[y]]) swap(x,y); return d[x]<d[y]?x:y;}
int jmp(int x,int t) {for(;d[top[x]]>t;x=f[top[x]]); return idf[dfn[x]-(d[x]-t)];}
inline bool cmp(const int &x,const int &y) {return dfn[x]<dfn[y];}
void d3(int x) {p[++lm]=x; int i;if(!vis[x]) r[x]=-1;for(i=head[x];i;i=nxt[i])ff[to[i]]=x,d3(to[i]);head[x]=0;}
int main() {
n=rd(); int i,x,y;
for(i=1;i<n;i++) {
x=rd(), y=rd(); add(x,n+i), add(n+i,x); add(y,n+i), add(n+i,y);
}
fk[0]=1<<30; tot=2*n-1; root=0; gr(1,0); solve(root); d1(1,0); d2(1,1);
int Q=rd(); memset(head,0,sizeof(head)); cnt=0;
while(Q--) {
m=rd(); cnt=ans=0;
for(i=1;i<=m;i++) p[i]=rd(),r[p[i]]=rd()<<1,vis[p[i]]=1;
sort(p+1,p+m+1,cmp); S[tp=1]=1;
for(i=1;i<=m;i++) {
x=p[i]; y=lca(x,S[tp]);
while(d[y]<d[S[tp]]) {
if(d[y]>=d[S[tp-1]]) {
add(y,S[tp]); tp--;
if(S[tp]!=y) S[++tp]=y;
break;
}
add(S[tp-1],S[tp]); tp--;
}
if(S[tp]!=x) S[++tp]=x;
}
while(tp>1) add(S[tp-1],S[tp]),tp--;
lm=0; d3(1);
for(i=lm;i>1;i--) r[ff[p[i]]]=max(r[ff[p[i]]],r[p[i]]-(d[p[i]]-d[ff[p[i]]]));
for(i=2;i<=lm;i++) r[p[i]]=max(r[p[i]],r[ff[p[i]]]-(d[p[i]]-d[ff[p[i]]]));
for(i=1;i<=lm;i++) ans+=work(p[i],r[p[i]]);
for(i=2;i<=lm;i++) {
x=p[i],y=ff[x];
int z=jmp(x,(d[x]-r[x]+d[y]+r[y])>>1);
ans-=work(z,r[x]-(d[x]-d[z]));
}
printf("%d\n",ans);
for(i=1;i<=lm;i++) vis[p[i]]=0;
}
}
Codechef Union on Tree的更多相关文章
- Codechef Observing the Tree
Home » Practice(Hard) » Observing the Tree https://www.codechef.com/problems/QUERY Observing the T ...
- 【点分树】codechef Yet Another Tree Problem
已经连咕了好几天博客了:比较经典的题目 题目大意 给出一个 N 个点的树和$K_i$, 求每个点到其他所有点距离中第 $K_i$ 小的数值. 题目分析 做法一:点分树上$\log^3$ 首先暴力做法: ...
- Codechef Chef Cuts Tree
该思博的时候就思博到底,套路的时候不能再套路的一道题 首先我们将联通块的大小平方和进行转化,发现它就等价于连通点对数,而这个可以转化为连接两点的边数(距离)和 所以我们考虑第\(i\)天时,一个点对\ ...
- @codechef - KILLER@ Painting Tree
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个 N 个点的有根树,标号 1 到 N,以 1 为根.定义 ...
- GDB中文手册
用GDB调试程序GDB概述 2使用GDB 5GDB中运行UNIX的shell程序 8在GDB中运行程序 8调试已运行的程序 两种方法: 9暂停 / 恢复程序运行 9一.设置断点(BreakPoint) ...
- Linux高级编程--04.GDB调试程序(查看数据)
查看栈信息 当程序被停住了,你需要做的第一件事就是查看程序是在哪里停住的.当你的程序调用了一个函数,函数的地址,函数参数,函数内的局部变量都会被压入"栈"(Stack)中.你可以用 ...
- GDB 使用大法
一.GDB 我用的是 GCC+POWERSHELL+GDB, GDB刚刚接触也有很多要记的. 二.一个调试示例 tst.c #include <stdio.h> int func(int ...
- poj----(1470)Closest Common Ancestors(LCA)
Closest Common Ancestors Time Limit: 2000MS Memory Limit: 10000K Total Submissions: 15446 Accept ...
- poj----1330Nearest Common Ancestors(简单LCA)
题目连接 http://poj.org/problem?id=1330 就是构建一棵树,然后问你两个节点之间最近的公共父节点是谁? 代码: /*Source Code Problem: 1330 U ...
随机推荐
- static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?
答案:全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量.全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式. 这两者在存储方式上并无不同.这两者的区别虽在于非静态全 ...
- Python小白的发展之路之Python基础(二)【字符串、列表、集合、文件操作】
列表.元组操作 字符串操作 字典操作 集合操作 文件操作 字符编码与转码 1.列表.元组操作 (1)列表 列表是可变的(mutable)——可以改变列表的内容,这不同于字符串和元组,字符串和元组都是不 ...
- ubuntu14.04 desktop 32-bit kvm装windows xp
经过这几天来的折腾,总算是在ubuntu14.04用kvm装上了xp, 看不少的的贴,也绕了不少的圈,总的来说,非常感谢CSDN上的"上善若水75",看着他写的一个分类" ...
- 九度OJ 1002:Grading
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:18410 解决:4753 题目描述: Grading hundreds of thousands of Graduate Entrance ...
- html5plus (H5 WebApp)
是什么? 它是增强版的手机浏览器引擎, 让HTML5达到原生水平, 它提供WebApp的规范. 它结合MUI(前端框架) + HBuilder(开发工具) 即可迅速实现开发一个app. 快速起步? 1 ...
- 【python】-- SQLAlchemy操作MySQL
ORM.SQLAchemy orm英文全称object relational mapping,就是对象映射关系程序,简单来说就是类似python这种面向对象的程序来说一切皆对象,但是使用的数据库却都是 ...
- PAT 1053. 住房空置率 (20)
在不打扰居民的前提下,统计住房空置率的一种方法是根据每户用电量的连续变化规律进行判断.判断方法如下: 在观察期内,若存在超过一半的日子用电量低于某给定的阈值e,则该住房为“可能空置”: 若观察期超过某 ...
- Linux备份和回复mysql数据库
备份:mysqldump -u root -p密码 数据库名>/home/data.bak mysqldump -u root -p密码 数据库名.表名>/home/data.bak ...
- CSS选择器(三)
九.CSS 伪类 (Pseudo-classes) CSS 伪类用于向某些选择器添加特殊的效果. CSS 伪类 (Pseudo-classes)实例: 1.向文档中的超链接添加不同的颜色. <s ...
- Swift 闭包的简单学习
OC中已经学习了闭包 在swift里面 该怎么处理 不多说 上代码 //(num:Int) ->Bool是闭包的参数类型 func hasCloserMatch(arr :[Int], valu ...