zoukankan      html  css  js  c++  java
  • 【LOJ2402】「THUPC2017」天天爱射击 / Shooting(整体二分)

    点此看题面

    大致题意:(n)个区间,每个区间有一个权值,当权值变成(0)时消失。每个时刻将覆盖某一位置的所有区间权值减(1),求每个时刻有多少个区间在这一刻消失。

    前言

    整体二分裸题啊,太久没写过,就当练手吧。

    整体二分

    我们把木板和子弹放在一起,然后以时间为关键字二分。

    每次先枚举所有时间小于等于(mid)的子弹,在树状数组上把它对应的位置单点修改值加(1)

    然后,枚举木板,区间查询它所覆盖区间有多少子弹,如果子弹个数大于等于它的权值,就扔到左区间,否则将它权值减去子弹个数,然后扔到右区间。

    注意二分上界为(m+1),因为可能有木板到最后都没有消失。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 200000
    using namespace std;
    int n,m,ans[N+5];struct data {int x,y,k;}s[2*N+5],p1[2*N+5],p2[2*N+5];
    class FastIO
    {
    	private:
    		#define FS 100000
    		#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
    		#define pc(c) (C==E&&(clear(),0),*C++=c)
    		#define tn (x<<3)+(x<<1)
    		#define D isdigit(c=tc())
    		int T;char c,*A,*B,*C,*E,FI[FS],FO[FS],S[FS];
    	public:
    		I FastIO() {A=B=FI,C=FO,E=FO+FS;}
    		Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
    		Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
    		Tp I void writeln(Con Ty& x) {write(x),pc('
    ');}
    		I void clear() {fwrite(FO,1,C-FO,stdout),C=FO;}
    }F;
    class TreeArray//树状数组
    {
    	private:
    		int v[N+5];
    	public:
    		I void Upt(RI x,CI y) {W(x<=n) v[x]+=y,x+=x&-x;}
    		I int Qry(RI x) {RI t=0;W(x) t+=v[x],x-=x&-x;return t;}
    }T;
    I void Solve(CI L,CI R,CI l,CI r)//整体二分
    {
    	if(l==r) {for(RI i=L;i<=R;++i) s[i].y&&(++ans[l]);return;}RI i,t,t1=0,t2=0;int mid=l+r>>1;//边界统计答案
    	for(i=L;i<=R;++i) if(!s[i].y) s[i].k<=mid?(T.Upt(s[i].x,1),p1[++t1]=s[i]):p2[++t2]=s[i];else break;//枚举子弹
    	for(;i<=R;++i) s[i].k<=(t=T.Qry(s[i].y)-T.Qry(s[i].x-1))?p1[++t1]=s[i]:(s[i].k-=t,p2[++t2]=s[i]);//枚举木板
    	for(i=1;i<=t1;++i) !p1[i].y&&(T.Upt(p1[i].x,-1),0),s[L+i-1]=p1[i];for(i=1;i<=t2;++i) s[L+t1+i-1]=p2[i];//重新填充数组,同时注意清空树状数组
    	Solve(L,L+t1-1,l,mid),Solve(L+t1,R,mid+1,r);//继续递归求解
    }
    int main()
    {
    	RI i;for(F.read(n),F.read(m),i=1;i<=n;++i) F.read(s[m+i].x),F.read(s[m+i].y),F.read(s[m+i].k);//读入木板
    	for(i=1;i<=m;++i) F.read(s[i].x),s[i].k=i;//读入子弹
    	for(Solve(1,n+m,1,m+1),i=1;i<=m;++i) F.writeln(ans[i]);return F.clear(),0;//输出答案
    }
    
  • 相关阅读:
    Java中通过Class类获取Class对象的方法详解
    java访问权限表
    JAVA内部类小结
    私有静态成员内部类的一个应用:单例的实现
    JAVA中接口与抽象类
    jQuery添加和删除元素
    使用JQuery进行DOM操作
    类加载过程&对象的创建过程
    Spring JDBC 数据访问
    Spring的 AOP底层用到两种代理机制
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/LOJ2402.html
Copyright © 2011-2022 走看看