题面

传送门

思路

本题其实有在线做法......但是太难写了,退而求其次写了离线

基本思路就是,考虑一个盘子以及它能接到的所有水果

可以发现,这个水果的端点一定在这个盘子两端的“子树”内(加引号是因为可能是一条链顶端外面的“子树”)

那么,可以把模型抽象成:盘子就是矩形,两个端点就是两个维度上的限制,而水果就是点

一个水果可以被接住,当且仅当这个水果的点在某个盘子的矩形内部

考虑盘子的不同情况:

如果盘子是有一个折点的折链,那么两边的限制,就是两个端点的子树dfs序范围

如果盘子是一条从下到上的链,那么这个矩形实际上是有两个的:

假设链是(u,v),u是v的祖先,这条链上从u开始下一个点是x

那么,其中一维的限制显然是$[dfn[v],last[v]]$,

但是另一维上的限制实际上有两个拼起来:

$[1,dfn[x]-1]$和$[last[x]+1,n]$

这里实际上是得到了$u$外面的“子树”的dfs序范围

我们把这些链拆成矩形,然后跑一个整体二分,每次二分每个水果被多少个矩形覆盖

当前二分区间是$[l,r]$,如果$[l,mid]$中的覆盖矩形的数量大于要求的数量,就进入左边

否则,要求的数量减去这个覆盖矩形数量,并进入右边

这样总复杂度是$O(n\log^2n)$

实现的时候,可以把矩形的两个维度中小的那个放在x,大的放在y,注意这里不要写错了

Code

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cassert>
#include<queue>
#include<cmath>
#define las DEEP_DARK_FANTASY
#define lowbit(x) (x&(-x))
#define mp make_pair
using namespace std;
namespace IO
{
const int __S=(1<<20)+5;char __buf[__S],*__H,*__T;
inline char getc()
{
if(__H==__T) __T=(__H=__buf)+fread(__buf,1,__S,stdin);
if(__H==__T) return -1;
return *__H++;
}
template <class __I>inline void read(__I &__x)
{
__x=0;int __fg=1;char __c=getc();
while(!isdigit(__c)&&__c!='-') __c=getc();
if(__c=='-') __fg=-1,__c=getc();
while(isdigit(__c)) __x=__x*10+__c-'0',__c=getc();
__x*=__fg;
}
inline void readd(double &__x)
{
__x=0;double __fg=1.0;char __c=getc();
while(!isdigit(__c)&&__c!='-') __c=getc();
if(__c=='-') __fg=-1.0,__c=getc();
while(isdigit(__c)) __x=__x*10.0+__c-'0',__c=getc();
if(__c!='.'){__x=__x*__fg;return;}else while(!isdigit(__c)) __c=getc();
double __t=1e-1;while(isdigit(__c)) __x=__x+1.0*(__c-'0')*__t,__t=__t*0.1,__c=getc();
__x=__x*__fg;
}
inline void reads(char *__s,int __x)
{
char __c=getc();int __tot=__x-1;
while(__c<'a'||__c>'z') __c=getc();
while(__c>='a'&&__c<='z') __s[++__tot]=__c,__c=getc();
__s[++__tot]='\0';
}
char __obuf[__S],*__oS=__obuf,*__oT=__oS+__S-1,__c,__qu[55];int __qr;
inline void flush(){fwrite(__obuf,1,__oS-__obuf,stdout);__oS=__obuf;}
inline void putc(char __x){*__oS++ =__x;if(__oS==__oT) flush();}
template <class __I>inline void print(__I __x)
{
if(!__x) putc('0');
if(__x<0) putc('-'),__x=-__x;
while(__x) __qu[++__qr]=__x%10+'0',__x/=10;
while(__qr) putc(__qu[__qr--]);
}
inline void prints(const char *__s,const int __x)
{
int __len=strlen(__s+__x);
for(int __i=__x;__i<__len+__x;__i++) putc(__s[__i]);
}
inline void printd(long double __x,int __d)
{
long long __t=(long long)floor(__x);print(__t);putc('.');__x-=(double)__t;
while(__d--)
{
long double __y=__x*10.0;__x*=10.0;
int __c=(int)floor(__y+1e-9);if(__c==10) __c--;
putc(__c+'0');__x-=floor(__y);
}
}
inline void el(){putc('\n');}inline void sp(){putc(' ');}
}using namespace IO; inline int read(){
int re=0,flag=1;char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') flag=-1;
ch=getchar();
}
while(isdigit(ch)) re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
return re*flag;
}
int n,m,k,first[40010],cnte,dfn[40010],las[40010],st[40010][20],dep[40010],clk;
struct edge{
int to,next;
}a[100010];
inline void add(int u,int v){
a[++cnte]=(edge){v,first[u]};first[u]=cnte;
a[++cnte]=(edge){u,first[v]};first[v]=cnte;
}
void dfs(int u,int f){
int i,v;
st[u][0]=f;dep[u]=dep[f]+1;
dfn[u]=++clk;
for(i=first[u];~i;i=a[i].next){
v=a[i].to;if(v==f) continue;
dfs(v,u);
}
las[u]=clk;
}
void ST(){
int i,j;
for(j=1;j<=16;j++)
for(i=1;i<=n;i++)
st[i][j]=st[st[i][j-1]][j-1];
}
int getpre(int l,int r){
int i;
if(l==r) return l;
if(dep[l]>dep[r]) swap(l,r);
for(i=16;i>=0;i--) if(dep[st[r][i]]>dep[l]) r=st[r][i];
if(st[r][0]==l) return r;
else return 0;
}
struct mat{
int lx,rx,ly,ry,val,id;
}p[100010];int cntp;
inline bool cmp(mat l,mat r){
return l.val<r.val;
}
struct fru{
int x,y,id,ans,k;
}f[40010];
struct ele{
int l,r,id;
};
namespace BIT{
int a[100010];
void Add(int x,int val){
for(;x<=n;x+=lowbit(x)) a[x]+=val;
}
void add(int l,int r,int val){
Add(l,val);Add(r+1,-val);
}
int sum(int x){
int re=0;
for(;x>0;x-=lowbit(x)) re+=a[x];
return re;
}
}
queue<ele>q;
vector<int>s,le,ri;
vector<pair<int,int> >t;
inline bool cmps(int l,int r){
return f[l].x<f[r].x;
}
inline bool cmpt(pair<int,int>l,pair<int,int>r){
int vl,vr;
if(l.second) vl=p[l.first].rx;
else vl=p[l.first].lx;
if(r.second) vr=p[r.first].rx;
else vr=p[r.first].lx;
return vl<vr;
}
void solve(){
ele cur;int i,l,r,mid,j,tmp,tval;
for(i=1;i<=k;i++) q.push((ele){1,cntp,i}); while(!q.empty()){
cur=q.front();q.pop();
if(cur.l==cur.r){f[cur.id].ans=p[cur.l].val;continue;}
l=cur.l;
r=cur.r;
s.clear();
s.push_back(cur.id);
mid=(l+r)>>1;t.clear(); while(!q.empty()&&q.front().l==l&&q.front().r==r){
s.push_back(q.front().id);
q.pop();
}
sort(s.begin(),s.end(),cmps); for(i=l;i<=mid;i++){
t.push_back(mp(i,0));
t.push_back(mp(i,1));
}
sort(t.begin(),t.end(),cmpt); j=-1;le.clear();ri.clear();
for(i=0;i<t.size();i++){
if(t[i].second) tmp=p[t[i].first].rx;
else tmp=p[t[i].first].lx; while((j<((int)s.size()-1))&&(f[s[j+1]].x<tmp)){
j++;tval=BIT::sum(f[s[j]].y);
if(tval<f[s[j]].k){
f[s[j]].k-=tval;
ri.push_back(s[j]);
}
else{
le.push_back(s[j]);
}
}
if(t[i].second) BIT::add(p[t[i].first].ly,p[t[i].first].ry,-1);
else BIT::add(p[t[i].first].ly,p[t[i].first].ry,1);
}
while(j<((int)s.size()-1)){
j++;tval=BIT::sum(f[s[j]].y);
if(tval<f[s[j]].k){
f[s[j]].k-=tval;
ri.push_back(s[j]);
}
else{
le.push_back(s[j]);
}
}
for(auto lef:le) q.push((ele){l,mid,lef});
for(auto rig:ri) q.push((ele){mid+1,r,rig});
}
}
int main(){
read(n);read(m);read(k);
int i,t1,t2,t3,tmp;
memset(first,-1,sizeof(first));
for(i=1;i<n;i++){
read(t1);read(t2);
add(t1,t2);
}
dfs(1,0);ST();
for(i=1;i<=m;i++){
read(t1);read(t2);read(t3);
if(dep[t2]<dep[t1]) swap(t1,t2);
tmp=getpre(t1,t2);
if(tmp){
if(dfn[tmp]>1) p[++cntp]=(mat){1,dfn[tmp]-1+1,dfn[t2],las[t2],t3,i};
if(las[tmp]<n) p[++cntp]=(mat){dfn[t2],las[t2]+1,las[tmp]+1,n,t3,i};
}
else{
if(dfn[t2]<dfn[t1]) swap(t1,t2);
p[++cntp]=(mat){dfn[t1],las[t1]+1,dfn[t2],las[t2],t3,i};
}
} sort(p+1,p+cntp+1,cmp); for(i=1;i<=k;i++){
read(t1);read(t2);read(t3);
if(dfn[t1]>dfn[t2]) swap(t1,t2);
f[i]=(fru){dfn[t1],dfn[t2],i,0,t3};
}
solve();
for(i=1;i<=k;i++) print(f[i].ans),el();
flush();
}

[HNOI2015][bzoj4009] 接水果 [整体二分+扫描线]的更多相关文章

  1. BZOJ.4009.[HNOI2015]接水果(整体二分 扫描线)

    LOJ BZOJ 洛谷 又是一个三OJ rank1!=w= \(Description\) (还是感觉,为啥非要出那种题目背景啊=-=直接说不好么) 给定一棵树和一个路径集合(每条路径有一个权值).\ ...

  2. BZOJ 4009: [HNOI2015]接水果 (整体二分+扫描线 树状数组)

    整体二分+扫描线 树状数组 具体做法看这里a CODE #include <cctype> #include <cstdio> #include <cstring> ...

  3. [bzoj4009] [HNOI2015]接水果 整体二分+扫描线+dfs序+树状数组

    Description 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果. 由于她已经DT FC 了The big black, 她觉得这个游戏太简单了,于是发明了一个更 加 ...

  4. bzoj4009 [HNOI2015]接水果 整体二分+扫描线+树状数组+dfs序

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4009 题解 考虑怎样的情况就会有一个链覆盖另一个链. 设被覆盖的链为 \(a - b\),覆盖 ...

  5. 【BZOJ4009】[HNOI2015]接水果 DFS序+整体二分+扫描线+树状数组

    [BZOJ4009][HNOI2015]接水果 Description 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果.由于她已经DT FC 了The big black, ...

  6. [BZOJ4009][HNOI2015]接水果(整体二分)

    [HNOI2015]接水果 时间限制:60s      空间限制:512MB 题目描述 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果. 由于她已经DT FC 了The b ...

  7. BZOJ4009:[HNOI2015]接水果(整体二分版)

    浅谈离线分治算法:https://www.cnblogs.com/AKMer/p/10415556.html 题目传送门:https://lydsy.com/JudgeOnline/problem.p ...

  8. 接水果(fruit)——整体二分+扫描线

    题目 [题目描述] 风见幽香非常喜欢玩一个叫做 osu! 的游戏,其中她最喜欢玩的模式就是接水果.由于她已经 DT FC 了 The big black,她觉得这个游戏太简单了,于是发明了一个更加难的 ...

  9. luogu3242 接水果 (整体二分+树状数组)

    考虑整体二分,问题就变成了每个(水果)路径有多少个满足条件(权值)的(盘子)子路径 考虑一个盘子(a,b)表示两端点(不妨设dfn[a]<dfn[b]),那么他能接到的水果(u,v)一定满足(不 ...

随机推荐

  1. HDU.2561 第二小整数(water)

    题目来源:2561 题意分析:找出一堆数中第二小的整数,和题目说的一样 我的思路:冒泡或者sort()一下就ok了,但是我因为没看到多个测试用例还是吃了几记WA . ┭┮﹏┭┮ 完整代码: #incl ...

  2. 基于mybatis设计简单OA系统问题2

    1.<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <fm ...

  3. Intellij IDEA 像eclipse那样给maven添加依赖,且Intellij idea里在pom.xml里添加Maven依赖,本地仓库下拉列表显示包很少的血的经验

    打开pom.xml,在它里面使用快捷键:ALT+Insert  ————>点击dependency 再输入想要添加的依赖关键字,比如:输个spring   出现下图: 根据需求选择版本,完成以后 ...

  4. js点击获取标签里面id属性

    <html xmlns="http://www.w3.org/1999/xhtml"> <head > <title></title> ...

  5. IDEA的下载安装和激活

    1.下载网站http://www.jetbrains.com/ 2. 3. 4.注意要下载Ultimate版本 5.安装 下载完成后直接下一步,傻瓜式安装 6.激活,在图片位置输入激活码即可 !!!! ...

  6. 爬取多个url页面数据--手动实现

    # -*- coding: utf-8 -*- import scrapy from qiubaiByPages.items import QiubaibypagesItem class Qiubai ...

  7. B1081 检查密码 (15分)

    B1081 检查密码 (15分) 本题要求你帮助某网站的用户注册模块写一个密码合法性检查的小功能.该网站要求用户设置的密码必须由不少于6个字符组成,并且只能有英文字母.数字和小数点 .,还必须既有字母 ...

  8. pyhton,数据类型

    标准数据类型 Python3 中有六个标准的数据类型: Number(数字) String(字符串) Tuple(元组) List(列表) Sets(集合) Dictionary(字典) 重点是: 类 ...

  9. 2,Flask 中的 Render Redirect HttpResponse

    一,Flask中的HTTPResponse 在Flask 中的HttpResponse 在我们看来其实就是直接返回字符串 二,.Flask中的Redirect 每当访问"/redi" ...

  10. oracle 用户被锁定解锁方法

    修改了用户密码,第二天过来发现用户被锁定,晚上走的时候还好好的 . alter profile DEFAULT limit FAILED_LOGIN_ATTEMPTS UNLIMITED; alter ...