BZOJ4009:[HNOI2015]接水果
浅谈树状数组与线段树:https://www.cnblogs.com/AKMer/p/9946944.html
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=4009
把每个水果\((u,v)\)转化成平面上的一个点\((dfn[u],dfn[v])\)。
我们考虑一个盘子,它可以接的水果的点集应该是矩形状的。
假设盘子的两个点是\(u,v\):
1、当\(u,v\)的\(lca\)不是\(u,v\)之一时:
那么凡是在矩形\((dfn[u],dfn[v],dfn[u]+siz[u]-1,dfn[v]+siz[v]-1)\)内的点都可以被这个盘子接住。
2、当\(u,v\)的\(lca\)是\(u\)或\(v\)时:
假设\(lca\)是\(u\),\(node\)是\(u\)的儿子并且是\(v\)的祖先。那么这个时候存在两个矩阵:
\((1,dfn[v],dfn[node]-1,dfn[v]+siz[v]-1)\)与\((dfn[v],dfn[node]+siz[node],dfn[v]+siz[v]-1,n)\)
我们对于每个矩阵做扫描线,外层套一个值域线段树,然后把水果和盘子放在一起\(sort\),动态修改然后在线段树上二分查找就行了。
时间复杂度:\(O(nlog^2n)\)
空间复杂度:\(O(nlog^2n)\)
代码如下:
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int,int> pii;
const int maxn=4e4+4;
int n,P,Q,tot,tim,cnt;
int now[maxn],pre[maxn*2],son[maxn*2];
int dep[maxn],dfn[maxn],siz[maxn],f[maxn][17];
int a[maxn],b[maxn],tmp[maxn],c[maxn],ans[maxn];
int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
struct Project {
int x,y1,y2,k,opt;
Project() {}
Project(int _x,int _y1,int _y2,int _k,int _opt) {
x=_x,y1=_y1,y2=_y2,k=_k,opt=_opt;
}
bool operator<(const Project &a)const {
if(x==a.x)return (opt!=0)>(a.opt!=0);//当x相同时先修改
return x<a.x;
}
}p[maxn*3];
struct pos_segment_tree {
int tot;
int sum[maxn*175],ls[maxn*175],rs[maxn*175];
void change(int &p,int l,int r,int L,int R,int opt) {
if(!p)p=++tot;
if(L<=l&&r<=R) {sum[p]+=opt;return;}
int mid=(l+r)>>1;
if(R<=mid)change(ls[p],l,mid,L,R,opt);
else if(L>mid)change(rs[p],mid+1,r,L,R,opt);
else change(ls[p],l,mid,L,mid,opt),change(rs[p],mid+1,r,mid+1,R,opt);
}
int query(int p,int l,int r,int pos) {
if(l==r)return sum[p];
int mid=(l+r)>>1,res=sum[p];
if(pos<=mid)res+=query(ls[p],l,mid,pos);
else res+=query(rs[p],mid+1,r,pos);
return res;
}
}T_inside;
struct val_segment_tree {
int rt[maxn<<2];
void change(int p,int l,int r,int pos,int L,int R,int v) {
T_inside.change(rt[p],1,n,L,R,v);
if(l==r)return;
int mid=(l+r)>>1;
if(pos<=mid)change(p<<1,l,mid,pos,L,R,v);
else change(p<<1|1,mid+1,r,pos,L,R,v);
}
int query(int p,int l,int r,int pos,int rk) {
if(l==r)return tmp[l];
int mid=(l+r)>>1,tmp=T_inside.query(rt[p<<1],1,n,pos);
if(tmp>=rk)return query(p<<1,l,mid,pos,rk);
else return query(p<<1|1,mid+1,r,pos,rk-tmp);
}
}T_outside;
void add(int a,int b) {
pre[++tot]=now[a];
now[a]=tot,son[tot]=b;
}
void dfs(int fa,int u) {
dep[u]=dep[fa]+1,siz[u]=1;
f[u][0]=fa,dfn[u]=++tim;
for(int i=1;i<=16;i++)
f[u][i]=f[f[u][i-1]][i-1];
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(v!=fa)dfs(u,v),siz[u]+=siz[v];
}
pii lca(int u,int v) {
if(dep[u]<dep[v])swap(u,v);
for(int i=16;~i;i--)
if(dep[f[u][i]]>dep[v])
u=f[u][i];
if(f[u][0]==v)return make_pair(v,u);
if(dep[u]>dep[v])u=f[u][0];
for(int i=16;~i;i--)
if(f[u][i]!=f[v][i])
u=f[u][i],v=f[v][i];
return make_pair(f[u][0],0);
}
int main() {
n=read(),P=read(),Q=read();
for(int i=1;i<n;i++) {
int a=read(),b=read();
add(a,b),add(b,a);
}dfs(0,1);tot=Q;
for(int i=1;i<=P;i++)
a[i]=read(),b[i]=read(),tmp[i]=c[i]=read();
sort(tmp+1,tmp+P+1);
cnt=unique(tmp+1,tmp+P+1)-tmp-1;
for(int i=1;i<=P;i++)
c[i]=lower_bound(tmp+1,tmp+cnt+1,c[i])-tmp;
for(int i=1;i<=Q;i++) {
int a=read(),b=read();
a=dfn[a],b=dfn[b];
p[i].x=min(a,b);p[i].y1=max(a,b);
p[i].k=read(),p[i].y2=i;
}
for(int i=1;i<=P;i++) {
if(dep[a[i]]<dep[b[i]])swap(a[i],b[i]);
pii tmp=lca(a[i],b[i]);
int u=tmp.first,v=tmp.second;
int l=dfn[a[i]],r=dfn[a[i]]+siz[a[i]]-1;
if(u==b[i]) {
int L=1,R=dfn[v]-1;
if(L<=R) {
p[++tot]=Project(L,l,r,c[i],1);
p[++tot]=Project(R+1,l,r,c[i],-1);//R+1是因为要差分
}
L=dfn[v]+siz[v],R=n;
if(L<=R) {
p[++tot]=Project(l,L,R,c[i],1);
p[++tot]=Project(r+1,L,R,c[i],-1);
}
}
else {
int L=dfn[b[i]],R=dfn[b[i]]+siz[b[i]]-1;
if(r>R)swap(l,L),swap(r,R);
p[++tot]=Project(l,L,R,c[i],1);
p[++tot]=Project(r+1,L,R,c[i],-1);
}
}
sort(p+1,p+tot+1);
for(int i=1;i<=tot;i++) {
if(p[i].opt==0)ans[p[i].y2]=T_outside.query(1,1,cnt,p[i].y1,p[i].k);
else T_outside.change(1,1,cnt,p[i].k,p[i].y1,p[i].y2,p[i].opt);
}
for(int i=1;i<=Q;i++)
printf("%d\n",ans[i]);
return 0;
}
BZOJ4009:[HNOI2015]接水果的更多相关文章
- [BZOJ4009][HNOI2015]接水果(整体二分)
[HNOI2015]接水果 时间限制:60s 空间限制:512MB 题目描述 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果. 由于她已经DT FC 了The b ...
- BZOJ4009: [HNOI2015]接水果
4009: [HNOI2015]接水果 Description 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果. 由于她已经DT FC 了The big black, 她 ...
- 2018.10.02 bzoj4009: [HNOI2015]接水果(整体二分)
传送门 整体二分好题. 考虑水果被盘子接住的条件. 不妨设水果表示的路径为(x1,y1)(x_1,y_1)(x1,y1),盘子表示的为(x2,y2)(x_2,y_2)(x2,y2) 不妨设df ...
- [bzoj4009] [HNOI2015]接水果 整体二分+扫描线+dfs序+树状数组
Description 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果. 由于她已经DT FC 了The big black, 她觉得这个游戏太简单了,于是发明了一个更 加 ...
- bzoj4009: [HNOI2015]接水果(整体二分)
题目描述 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果.由于她已经DT FC 了The big black, 她觉得这个游戏太简单了,于是发明了一个更加难的版本. 首先有 ...
- bzoj4009 [HNOI2015]接水果 整体二分+扫描线+树状数组+dfs序
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4009 题解 考虑怎样的情况就会有一个链覆盖另一个链. 设被覆盖的链为 \(a - b\),覆盖 ...
- 【BZOJ4009】[HNOI2015]接水果 DFS序+整体二分+扫描线+树状数组
[BZOJ4009][HNOI2015]接水果 Description 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果.由于她已经DT FC 了The big black, ...
- 【BZOJ4009】接水果(整体二分,扫描线)
[BZOJ4009]接水果(整体二分,扫描线) 题面 为什么这都是权限题???,洛谷真良心 题解 看到这道题,感觉就是主席树/整体二分之类的东西 (因为要求第\(k\)大) 但是,读完题目之后,我们发 ...
- BZOJ 4009: [HNOI2015]接水果
4009: [HNOI2015]接水果 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 636 Solved: 300[Submit][Status] ...
- 洛谷 P3242 [HNOI2015]接水果 解题报告
P3242 [HNOI2015]接水果 题目描述 风见幽香非常喜欢玩一个叫做 \(osu!\) 的游戏,其中她最喜欢玩的模式就是接水果.由于她已经\(DT\) \(FC\) 了\(\tt{The\ b ...
随机推荐
- 【HTML5开发系列】DOM及其相关
对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标志语言的标准编程接口.DOM把Javascript和HTML文档的结构和内容连接起来,通过DOM可以控 ...
- OSI模型第三层网络层-初识路由协议
1.路由协议: 顾名思义就是路由器所使用的协议. 分类: (1)按照作用范围分类,IGP(类型)内部网关协议(rip,ospf,isis),EGP(类型)边界路由协议(bgp) 把互联网比作整个世界土 ...
- 九度OJ 1196:成绩排序 (排序)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:4339 解决:1476 题目描述: 用一维数组存储学号和成绩,然后,按成绩排序输出. 输入: 输入第一行包括一个整数N(1<=N< ...
- 【python】-- Socket接收大数据
Socket接收大数据 上一篇博客中的简单ssh实例,就是说当服务器发送至客户端的数据,大于客户端设置的数据,则就会把数据服务端发过来的数据剩余数据存在IO缓冲区中,这样就会造成我们想要获取数据的完整 ...
- php自定义的格式化时间示例代码
时间刚好是5分钟前,则对应的时间戳就会被格式化为5分钟前,自定义的格式化时间方法如下,感兴趣的朋友可以参考下 如:时间刚好是5分钟前,则对应的时间戳就会被格式化为5分钟前,不多说了,直接贴上代码: 复 ...
- 3.19课·········HTML---标签与表格
HTML(Hyper Text Markup Language,超文本标记语言) <html> ------开始标签 <head>----网页上的控制信息 <title& ...
- c++之默认参数的函数
默认参数,看个例子就明白了 int add(int a=5,int b=6,z=3): int main(){ add():// 全部默认 add(1,5)://第三个参数默认 add(1,2,3): ...
- 每天一个Linux命令(8)cat命令
cat命令连接文件并打印到标准输出设备上,cat经常用来显示文件的内容,类似于下的type命令. 注意:当文件较大时,文本在屏幕上迅速闪过(滚屏),用户往往看不清所显示的内容.因此,一般用more等命 ...
- Java多线程系列 JUC线程池01 线程池框架
转载 http://www.cnblogs.com/skywang12345/p/3509903.html 为什么引入Executor线程池框架 new Thread()的缺点 1. 每次new T ...
- [原创]java WEB学习笔记25:MVC案例完整实践(part 6)---新增操作的设计与实现
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...