题面

传送门

思路

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

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

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

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

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

考虑盘子的不同情况:

如果盘子是有一个折点的折链,那么两边的限制,就是两个端点的子树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. jquery-ui-custom autocomplete

    //jsp <%@ page language="java" import="java.util.*" pageEncoding="utf-8& ...

  2. 关于js的严格模式

    最近在看你不知道js,补充自己的js基础,加深理解.在读的过程中写点笔记. 严格模式下与非严格模式的区别 . 严格模式是es5新增的,es6是默认为严格模式的!js默认状态下是非严格模式的!   一般 ...

  3. LeetCode700. Search in a Binary Search Tree

    题目 给定二叉搜索树(BST)的根节点和一个值. 你需要在BST中找到节点值等于给定值的节点. 返回以该节点为根的子树. 如果节点不存在,则返回 NULL. 例如, 给定二叉搜索树: 4 / \ 2 ...

  4. REST Adapter实现SAP PI中的增强XML/JSON格式转换(转载)

    SAP标准的REST adapter有着XML/JSON转换的功能,它很有用,因为一方面SAP PI/PO内部以XML格式处理数据,而另一方面,在处理REST架构风格的时候,JSON才是事实上的格式. ...

  5. motto - question - bodyParser.urlencoded 中设置 extended 为 true 和 false 有什么区别吗?

    本文搜索关键字:motto node nodejs js javascript body-parser bodyparser urlencoded x-www-form-urlencoded exte ...

  6. MySQL为何不建议使用null列

      Preface       Null is a special constraint of columns.The columns in table will be added null cons ...

  7. MySQL另类的备份恢复方法——innodb可传输表空间

      Preface       There're many ways in backing up or migrating data from one server to another one.Lo ...

  8. 前端vue项目部署到tomcat,一刷新报错404解决方法

    公司前端写的后台部署到tomcat webapps目录下后,无法进行刷新,一刷新就会报错404,自动跳的404页面.在网上查了下,官方说是HTML5 History 模式引发的问题,但是解决方案中,并 ...

  9. Linux实战教学笔记16:磁盘原理

    第十五节 磁盘原理 标签(空格分隔): Linux实战教学笔记 1,知识扩展 非脚本方式的一条命令搞定批量创建用户并设置随机10位字母数字组合密码. 1.1 sed的高级用法 [root@chensi ...

  10. Java OOP——第五章 异常

    1. 尝试通过if-else来解决异常问题: Eg: public class Test2 {       public static void main(String[] args) {       ...