zoukankan      html  css  js  c++  java
  • bzoj3110[Zjoi2013]K大数查询

    刚刚学习了整体二分,练习一下。

    太长时间没写线段树了,结果在这道题里,线段树没有写update函数,怎么调都调不出来,无奈只好翻别人程序,改了一下就过了。

    还有一个非常麻烦的事情是边界问题,程序里有一些需要打小于,有一些打小于等于,解决这个问题一种方法是对程序逻辑良好的整体把握,另一种方法是大力对拍,把可能情况测一遍就行了。

    样例太水,不要相信样例。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define LL  long long
    #define FILE "dealing"
    #define up(i,j,n) for(int i=j;i<=n;i++)
    LL read(){
    	LL x=0,f=1,ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    	return x*f;
    }
    const LL maxn=800000,mod=1000000007,inf=10000000000000LL;
    bool cmin(LL& a,LL b){return a>b?a=b,true:false;}
    bool cmax(LL& a,LL b){return a<b?a=b,true:false;}
    LL n,m;
    struct node{LL x,y,op,ans,k,id;}a[maxn],q1[maxn],q2[maxn];
    bool cmp(node a,node b){return a.id<b.id;}
    LL key,left,right;
    LL delet[maxn],s[maxn],siz[maxn],flag[maxn];
    void add(LL x,LL del){delet[x]+=del,s[x]+=siz[x]*del;}
    void qing(LL x){delet[x]=s[x]=0;flag[x]=1;}
    void updata(LL x){s[x]=s[x<<1]+s[x<<1|1];}
    void pushdown(LL x){
    	if(flag[x])qing(x<<1),qing(x<<1|1),flag[x]=0;
    	if(delet[x])add(x<<1,delet[x]),add(x<<1|1,delet[x]),delet[x]=0;
    }
    void change(LL l,LL r,LL o){
    	if(l>right||r<left)return;
    	if(l>=left&&r<=right){add(o,key);return;}
    	LL mid=(l+r)>>1;
    	pushdown(o);
    	change(l,mid,o<<1);
    	change(mid+1,r,o<<1|1);
    	updata(o);
    }
    void Change(LL L,LL R,LL d){
    	left=L,right=R,key=d;
    	change(1,n,1);
    }
    LL query(LL l,LL r,LL o){
    	if(r<left||l>right)return 0;
    	if(l>=left&&r<=right)return s[o];
    	LL mid=(l+r)>>1;
    	pushdown(o);
    	return query(l,mid,o<<1)+query(mid+1,r,o<<1|1);
    }
    LL Query(LL L,LL R){
    	left=L,right=R;
    	return query(1,n,1);
    }
    void build(LL l,LL r,LL o){
    	if(l==r){siz[o]=1;return;}
    	LL mid=(l+r)>>1;
    	build(l,mid,o<<1);
    	build(mid+1,r,o<<1|1);
    	siz[o]=siz[o<<1]+siz[o<<1|1];
    }
    LL sum[maxn];
    void divide(LL L,LL R,LL l,LL r){
    	if(l>r)return;
    	if(L==R){
    		up(i,l,r)if(a[i].op==2)a[i].ans=L;
    		return;
    	}
    	qing(1);
    	LL mid=(L+R)>>1;
    	up(i,l,r){
    		if(a[i].op==1&&a[i].k>mid)Change(a[i].x,a[i].y,1);
    		else if(a[i].op==2)sum[i]=Query(a[i].x,a[i].y);
    	}
    	LL top1=0,top2=0;
    	up(i,l,r){
    		if(a[i].op==2){
    			if(sum[i]<=a[i].k){
    				a[i].k-=sum[i];
    				q1[++top1]=a[i];
    			}else q2[++top2]=a[i];
    		}
    		else {
    			if(a[i].k>mid)q2[++top2]=a[i];
    			else q1[++top1]=a[i];
    		}
    	}
    	up(i,l,l+top1-1)a[i]=q1[i-l+1];
    	up(i,l+top1,r)a[i]=q2[i-top1-l+1];
    	divide(L,mid,l,l+top1-1);
    	divide(mid+1,R,l+top1,r);
    }
    int main(){
    	freopen(FILE".in","r",stdin);
    	freopen(FILE".out","w",stdout);
    	n=read(),m=read();LL Min=inf,Max=-inf;
    	up(i,1,m){
    		a[i].op=read(),a[i].x=read(),a[i].y=read(),a[i].k=read();a[i].id=i;
    		if(a[i].op==2)a[i].k-=1;
    		if(a[i].op==1)cmin(Min,a[i].k),cmax(Max,a[i].k);
    	}
    	build(1,n,1);
    	divide(Min,Max,1,m);
    	sort(a+1,a+m+1,cmp);
    	up(i,1,m)if(a[i].op==2)printf("%lld
    ",a[i].ans);
    	return 0;
    }
    

      

  • 相关阅读:
    对struts2的简单理解
    对xml文件封装思想的处理
    反射技术
    设计模式之观察者模式
    设计模式之单例模式
    浅谈对象的克隆
    细说 过滤篇
    flex html 用flex展示html
    git同一文件由于文件名大小写不同导致不能合并
    关于C#引用Dll后,找不到命名空间的问题
  • 原文地址:https://www.cnblogs.com/chadinblog/p/6439190.html
Copyright © 2011-2022 走看看