点此看题面

大致题意: 一颗星球被分为\(M\)份,分别属于\(N\)个国家,有\(K\)场陨石雨,第\(i\)个国家希望收集\(P_i\)颗陨石,问其至少要在第几次陨石雨后才能达到目标。

关于整体二分

什么是整体二分

其实我也不太清楚,反正就是一个很神仙的东西。

而这题的做法听说就是传说中的整体二分。

关于树状数组

这题我一开始写的是线段树,结果代码又长又\(TLE\)。

改成树状数组后就过了。

对于我之前说过的绝对不写树状数组,我只能说:真香。

大致思路

首先,我们将\(K\)场陨石雨\(N\)个询问全部用一个数组存储下来。

然后我们对时间进行二分,每次将第\(l\sim mid\)场陨石雨能在第\(mid\)个操作前达成的询问放入左半区间,将其余的陨石雨和询问放入右半区间,然后继续操作即可。

具体实现如下:

  • 先枚举陨石雨,将编号\(\le mid\)的陨石雨全部用树状数组进行区间修改。
  • 然后枚举询问,枚举当前国家的每一份(可以使用邻接表)统计陨石个数和,然后与\(P_i\)比较即可。

有一些小细节,还是见代码吧。

代码

#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define Gmax(x,y) (x<(y)&&(x=(y)))
#define Gmin(x,y) (x>(y)&&(x=(y)))
#define abs(x) ((x)<0?-(x):(x))
#define swap(x,y) (x^=y^=x^=y)
#define uint unsigned int
#define LL long long
#define ull unsigned long long
#define INF 1000000000
#define N 300000
#define M 300000
#define K 300000
using namespace std;
int n,m,k,t[N+5],lnk[N+5],nxt[M+5];
struct key
{
int op,pos,val,l,r;
key(int o=0,int p=0,int v=0,int x=0,int y=0):op(o),pos(p),val(v),l(x),r(y){}
}s[N+K+5];
class Class_FIO
{
private:
#define Fsize 100000
#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,Fsize,stdin),A==B)?EOF:*A++)
#define pc(ch) (void)(FoutSize<Fsize?Fout[FoutSize++]=ch:(fwrite(Fout,1,FoutSize,stdout),Fout[(FoutSize=0)++]=ch))
int f,FoutSize,Top;char ch,Fin[Fsize],*A,*B,Fout[Fsize],Stack[Fsize];
public:
Class_FIO() {A=B=Fin;}
inline void read(int &x) {x=0,f=1;while(!isdigit(ch=tc())) f=ch^'-'?1:-1;while(x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));x*=f;}
inline void write(int x) {if(!x) return pc('0');x<0&&(pc('-'),x=-x);while(x) Stack[++Top]=x%10+48,x/=10;while(Top) pc(Stack[Top--]);}
inline void writec(char x) {pc(x);}
inline void write_NoAnswer() {pc('N'),pc('I'),pc('E'),pc('\n');}
inline void clear() {fwrite(Fout,1,FoutSize,stdout),FoutSize=0;}
}F;
class Class_DivideSolver
{
private:
int ans[N+5];key ns1[N+K+5],ns2[N+K+5];
class Class_TreeArray//树状数组
{
private:
#define lowbit(x) ((x)&-(x))
LL num[M+5];
public:
inline void Update(int x,LL val) {while(x<=m) num[x]+=val,x+=lowbit(x);}
inline LL Query(int x,LL res=0) {while(x) res+=num[x],x-=lowbit(x);return res;}
}T;
public:
inline void Solve(int l=1,int r=n+k,int L=1,int R=k+1)//整体二分
{
register int i,j,mid=L+R>>1,cnt1=0,cnt2=0;register LL tot;
if(!(L^R)) {for(i=l;i<=r;++i) !s[i].op&&(ans[s[i].pos]=L);return;}//判边界
for(i=l;i<=r;++i)//枚举操作
{
if(s[i].op)//对于陨石雨
{
if(s[i].pos<=mid) (s[i].l<=s[i].r?(T.Update(s[i].l,s[i].val),T.Update(s[i].r+1,-s[i].val)):(T.Update(s[i].l,s[i].val),T.Update(1,s[i].val),T.Update(s[i].r+1,-s[i].val))),ns1[++cnt1]=s[i];//树状数组区间修改,并将其扔入左半部分
else ns2[++cnt2]=s[i];continue;//否则将其扔入右半部分
}
for(tot=0,j=lnk[s[i].pos];j;j=nxt[j]) if((tot+=T.Query(j))>=s[i].val) break;//统计陨石个数和,注意达成条件后直接break
tot>=s[i].val?ns1[++cnt1]=s[i]:(s[i].val-=tot,ns2[++cnt2]=s[i]);//比较tot与s[i].val,来判断将其扔入左半区间还是右半区间
}
for(i=1;i<=cnt1;++i) s[l+i-1]=ns1[i];for(i=1;i<=cnt2;++i) s[l+cnt1+i-1]=ns2[i];//更新序列
for(i=l;i<=r;++i) s[i].op&&s[i].pos<=mid&&(s[i].l<=s[i].r?(T.Update(s[i].l,-s[i].val),T.Update(s[i].r+1,s[i].val)):(T.Update(s[i].l,-s[i].val),T.Update(1,-s[i].val),T.Update(s[i].r+1,s[i].val)),0);//清空树状数组
cnt1&&(Solve(l,l+cnt1-1,L,mid),0),cnt2&&(Solve(l+cnt1,r,mid+1,R),0);//继续处理子区间
}
inline void Print() {for(register int i=1;i<=n;++i) ans[i]<=k?F.write(ans[i]),F.writec('\n'):F.write_NoAnswer();}//输出答案
}D;
int main()
{
register int i,x,y,z;
for(F.read(n),F.read(m),i=1;i<=m;++i) F.read(x),nxt[i]=lnk[x],lnk[x]=i;
for(i=1;i<=n;++i) F.read(t[i]);
for(F.read(k),i=1;i<=k;++i) F.read(x),F.read(y),F.read(z),s[i]=key(1,i,z,x,y);//存储陨石雨
for(i=1;i<=n;++i) s[i+k]=key(0,i,t[i]);//存储询问
return D.Solve(),D.Print(),F.clear(),0;
}

【洛谷3527】[POI2011] MET-Meteors(树状数组+整体二分)的更多相关文章

  1. [洛谷P1198/BZOJ1012][JSOI2008] 最大数 - 树状数组/线段树?

    其实已经学了树状数组和线段树,然而懒得做题,所以至今没写多少博客 Description 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数 ...

  2. 洛谷P3688/uoj#291. [ZJOI2017]树状数组

    传送门(uoj) 传送门(洛谷) 这里是题解以及我的卡常数历程 话说后面那几组数据莫不是lxl出的这么毒 首先不难发现这个东西把查询前缀和变成了查询后缀和,结果就是查了\([l-1,r-1]\)的区间 ...

  3. 洛谷P3368 【模板】树状数组 2

    P3368 [模板]树状数组 2 102通过 206提交 题目提供者HansBug 标签 难度普及/提高- 提交  讨论  题解 最新讨论 暂时没有讨论 题目描述 如题,已知一个数列,你需要进行下面两 ...

  4. 洛谷P3374 【模板】树状数组 1

    P3374 [模板]树状数组 1 140通过 232提交 题目提供者HansBug 标签 难度普及/提高- 提交  讨论  题解 最新讨论 题目描述有误 题目描述 如题,已知一个数列,你需要进行下面两 ...

  5. 洛谷 P3368 【模板】树状数组 2

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...

  6. 洛谷 P3374 【模板】树状数组 1

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...

  7. 树状数组模板(pascal) 洛谷P3374 【模板】树状数组1

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...

  8. 洛谷1527(bzoj2738)矩阵乘法——二维树状数组+整体二分

    题目:https://www.luogu.org/problemnew/show/P1527 不难想到(?)可以用二维树状数组.但维护什么?怎么查询是难点. 因为求第k小,可以考虑记权值树状数组,把比 ...

  9. 洛谷P1527 矩阵乘法——二维树状数组+整体二分

    题目:https://www.luogu.org/problemnew/show/P1527 整体二分,先把所有询问都存下来: 然后二分一个值,小于它的加到二维树状数组的前缀和里,判断一遍所有询问,就 ...

随机推荐

  1. flask-sqlalchemy中 backref lazy的参数实例解释和选择

    官方文档:http://docs.sqlalchemy.org/en/rel_1_0/orm/basic_relationships.html#relationship-patterns 最近在学习到 ...

  2. 前端页面唯一字符串生成(Js)UUID

    function uuid() { var s = []; var hexDigits = "0123456789abcdef"; for (var i = 0; i < 3 ...

  3. Spark BlockManager 概述

    Application 启动的时候: 1. 会在 SparkEnv 中实例化 BlockManagerMaster 和 MapOutputTracker,其中 (a) BlockManagerMast ...

  4. 三层登录——VB.NET版

    前言 由于下面的机房收费系统重构自己要用VB.NET进行重构,所以在敲三层登录的时候,实践了一份C#版三层登录,接着就是VB.NET版的三层登录.话说还有七层登录,一下子感觉三层又矮小了.万丈高楼平地 ...

  5. 【转】vs发布msi程序详解

    源地址:http://wenku.baidu.com/link?url=MV1Mf7IukCZ0cab8AzXQoQ3MAXeUAHGz5b2IuUL4Kw-hCI90ZyBKXwKeQA3t3-SV ...

  6. hdu 1729 Stone Game

    Stone Game HDU - 1729 题意: 给定n个箱子,每个箱子的容量为si,每个箱子里最初有ci个石子,每次放入石子不能超过放入前的石子数的平方,谁无法继续放入石子就算输.   /* 这是 ...

  7. oracle例程

    原创转载请注明出处 启动例程: 数据库启动例程的3个步骤 启动例程(NOMOUNT状态):读取参数文件,分配SGA和启动后台进程. 装载数据库(MOUNT状态):根据初始化参数control_file ...

  8. day16正则表达式作业详解

    1.正则表达式练习题 点击查看详细内容 作业的讲解 1.匹配整数或者小数(包括正数和负数) -?\d+.\d+|-?\d+ -?\d+(\.\d+)? 2.匹配年月日日期 格式2018-12-6 #找 ...

  9. 【C#】C#委托使用详解(Delegates)

    摘要 委托是C#编程一个非常重要的概念,也是一个难点.本文将系统详细讲解委托. 1. 委托是什么? 其实,我一直思考如何讲解委托,才能把委托说得更透彻.说实话,每个人都委托都有不同的见解,因为看问题的 ...

  10. InteliJ idea import project 找不到文件结构解决办法

    一.按下列步骤操作:       1. 关闭IDEA,        2.然后删除项目文件夹下的.idea文件夹       3.重新用IDEA工具打开项目: 二.import新项目之后,可能需要等1 ...