zoukankan      html  css  js  c++  java
  • 3332[ZJOI2013]K大数查询

    3332[ZJOI2013]K大数查询

    题面:洛谷

    解析

    离线算法好啊(废话,不然为什么离线)!这道题带区间修改查询(k)小值,如果树套树,要用线段树套线段树,外层维护权值,里层维护区间,复杂度(O(nlog^{2}{n})),但我们可以用整体二分,虽然复杂度也是(O(nlog^{2}{n})),但是常数小啊,代码又好写。依然是二分第(k)小的数值,用树状数组维护即可(常数小)。

    代码

    
    #include<cstdio>
    #define LL long long
    #define N 50005
    #define I inline
    using namespace std;
    int n,m,id[N],t1[N],t2[N],ans[N];
    struct Q{ int op,l,r; LL val; }q[N];
    LL a1[N],a2[N];
    I int In(){
    	char c=getchar(); int x=0,ft=1;
    	for(;c<'0'||c>'9';c=getchar()) if(c=='-') ft=-1;
    	for(;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
    	return x*ft;
    }
    I int LB(int x){ return x&(-x); }
    I void Add1(int x,int C){ for(int i=x;i<=n;i+=LB(i)) a1[i]+=C; }
    I LL Sum1(int x){ LL s=0; for(int i=x;i;i-=LB(i)) s+=a1[i]; return s; }
    I void Add2(int x,int C){ for(int i=x;i<=n;i+=LB(i)) a2[i]+=(LL)C*x; }
    I LL Sum2(int x){ LL s=0; for(int i=x;i;i-=LB(i)) s+=a2[i]; return s; }
    I void Modify(int l,int r,int C){ Add1(l,C); Add1(r+1,-C); Add2(l,C); Add2(r+1,-C); }
    I LL Query(int l,int r){ return (LL)Sum1(r)*(r+1)-Sum2(r)-(LL)Sum1(l-1)*l+Sum2(l-1); }
    void Solve(int l,int r,int ql,int qr){
    	if(ql>qr) return;
    	if(l==r){
    		for(int i=ql;i<=qr;++i) ans[id[i]]=l;
    		return;
    	}
    	int mid=(l+r+1)/2,p1=0,p2=0;
    	for(int i=ql,u;i<=qr;++i){
    		u=id[i];
    		if(q[u].op==1){
    			if(q[u].val>=mid) Modify(q[u].l,q[u].r,1),t1[++p1]=u;
    			else t2[++p2]=u;
    		}
    		if(q[u].op==2){
    			LL x=Query(q[u].l,q[u].r);
    			if(x>=q[u].val) t1[++p1]=u;
    			else q[u].val-=x,t2[++p2]=u;
    		}
    	}
    	for(int i=ql,u;i<=qr;++i){
    		u=id[i];
    		if(q[u].op==1&&q[u].val>=mid)
    		Modify(q[u].l,q[u].r,-1);
    	}
    	for(int i=ql;i<=ql+p1-1;++i) id[i]=t1[i-ql+1];
    	for(int i=ql+p1;i<=qr;++i) id[i]=t2[i-ql-p1+1];
    	Solve(mid,r,ql,ql+p1-1); Solve(l,mid-1,ql+p1,qr);
    }
    int main(){
    	n=In(); m=In();
    	for(int i=1;i<=m;++i){
    		id[i]=i; q[i].op=In(); q[i].l=In();
    		q[i].r=In(); scanf("%lld",&q[i].val);
    	}
    	Solve(-n,n,1,m);
    	for(int i=1;i<=m;++i) if(q[i].op==2) printf("%d
    ",ans[i]);
    	return 0;
    }
    
    
  • 相关阅读:
    ZOJ 2588 Burning Bridges
    POJ 1966 ZOJ 2182 Cable TV Network
    HDU 5348 MZL's endless loop
    HDU 5352 MZL's City
    Tarjan算法求解无向连通图的割点、割边、点双连通分量和边双连通分量的模板
    ZOJ 1119 SPF
    HDU 3452 Bonsai
    HDU 1520 Anniversary party
    POJ 2239 Selecting Courses
    POJ 1144 Network
  • 原文地址:https://www.cnblogs.com/pkh68/p/10526841.html
Copyright © 2011-2022 走看看