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

    题解:整体二分答案即可

    #include <bits/stdc++.h>
    #define ll long long
    const int MAXN=5e4+10;
    using namespace std;
    ll sum1[MAXN],sum2[MAXN];
    int n,m;
    vector<int>vec;
    int get_id(int x){return x&(-x);}
    void update1(int x,ll vul){
    	if(!x)return ;
    	for(int i=x;i>0;i-=get_id(i))sum1[i]+=vul;
    }
    ll Sum1(int x){
    	if(!x)return 0;
    	ll ans=0;
    	for(int i=x;i<=n;i+=get_id(i))ans+=sum1[i];
    	return ans;
    }
    void update2(int x,ll vul){
    	if(!x)return ;
    	for(int i=x;i<=n;i+=get_id(i))sum2[i]+=vul;
    }
    ll Sum2(int x){
    	if(!x)return 0;
    	ll ans=0;
    	for(int i=x;i>0;i-=get_id(i))ans+=sum2[i];
    	return ans;
    }
    typedef struct node{
    	int op,l,r;ll c,cnt,ans;
    }node;
    node que[MAXN];
    int id[MAXN],ed[MAXN],ip[MAXN];
    void update(int t){
    	update2(que[t].r,que[t].r);update1(que[t].r-1,1);
    	update2(que[t].l,1-que[t].l);update1(que[t].l-1,-1);
    }
    void clear(int t){
    	update2(que[t].r,-1*que[t].r);update1(que[t].r-1,-1);
    	update2(que[t].l,que[t].l-1);update1(que[t].l-1,1);	
    }
    ll querty(int t){
    	ll ans=0;ans+=Sum2(que[t].r)+1LL*que[t].r*Sum1(que[t].r);
    	ans-=(Sum2(que[t].l-1)+1LL*(que[t].l-1)*Sum1(que[t].l-1));
    	return ans;
    }
    int flag=0;
    void slove(int ql,int qr,int l,int r){
    	if(ql>qr||l>r)return ;
    	int mid=(l+r)>>1;
    	int cnt1=0,cnt2=0;
    	//cout<<vec[mid-1]<<" "<<mid<<endl;
    	for(int i=ql;i<=qr;i++){
    		if(que[id[i]].op==1){
    			if(que[id[i]].c>=vec[mid-1])ip[++cnt1]=id[i],update(id[i]);
    			else ed[++cnt2]=id[i];
    		}
    		else{
    			//cout<<querty(id[i])<<" "<<que[id[i]].cnt<<" "<<que[id[i]].c<<" "<<id[i]<<endl;
    			if(querty(id[i])+que[id[i]].cnt>=que[id[i]].c)ip[++cnt1]=id[i],que[id[i]].ans=vec[mid-1];
    			else ed[++cnt2]=id[i],que[id[i]].cnt+=querty(id[i]);
    		}
    	}
    	//if(flag==2)cout<<cnt2<<" "<<cnt1<<" "<<mid<<endl;
    	//flag++;
    	for(int i=ql;i<=qr;i++){if(que[id[i]].op==1&&que[id[i]].c>=vec[mid-1])clear(id[i]);}
    	//for(int i=1;i<=n;i++)sum1[i]=sum2[i]=0;
    	for(int i=1;i<=cnt2;i++)id[ql+i-1]=ed[i];
    	for(int i=1;i<=cnt1;i++)id[ql+cnt2+i-1]=ip[i];
    	slove(ql,ql+cnt2-1,l,mid-1);
    	slove(ql+cnt2,qr,mid+1,r);
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++){
    		scanf("%d%d%d%lld",&que[i].op,&que[i].l,&que[i].r,&que[i].c),id[i]=i,que[i].cnt=0;
    		if(que[i].op==1)vec.push_back(que[i].c);
    	}
    	sort(vec.begin(),vec.end());
    	int sz=unique(vec.begin(),vec.end())-vec.begin();
    	slove(1,m,1,sz);
    	for(int i=1;i<=m;i++){
    		if(que[i].op==2)printf("%lld
    ",que[i].ans);
    	}
    }
    

    3110: [Zjoi2013]K大数查询

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 11674  Solved: 3512
    [Submit][Status][Discuss]

    Description

    有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c
    如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。

    Input

    第一行N,M
    接下来M行,每行形如1 a b c或2 a b c

    Output

    输出每个询问的结果

    Sample Input

    2 5
    1 1 2 1
    1 1 2 2
    2 1 1 2
    2 1 1 1
    2 1 2 3

    Sample Output

    1
    2
    1

    HINT



    【样例说明】

    第一个操作 后位置 1 的数只有 1 , 位置 2 的数也只有 1 。 第二个操作 后位置 1

    的数有 1 、 2 ,位置 2 的数也有 1 、 2 。 第三次询问 位置 1 到位置 1 第 2 大的数 是

    1 。 第四次询问 位置 1 到位置 1 第 1 大的数是 2 。 第五次询问 位置 1 到位置 2 第 3

    大的数是 1 。‍

    N,M<=50000,N,M<=50000

    a<=b<=N

    1操作中abs(c)<=N

    2操作中c<=Maxlongint

  • 相关阅读:
    【2016-11-6】【坚持学习】【Day21】【主窗口关闭时,同步关闭它的子窗口】
    【2016-11-5】【坚持学习】【Day20】【通过委托事件,关闭窗口】
    【2016-11-5】【坚持学习】【Day20】【Linq where in 语句】
    【2016-11-4】【坚持学习】【Day19】【MVVM ICommand】
    【2016-11-5】【坚持学习】【Day20】【MVVM DelegateCommand】
    【2016-11-3】【坚持学习】【Day18】【我认识的ORM】
    【2016-11-3】【坚持学习】【Day18】【Oracle 数据类型 与C#映射关系】
    【2016-11-3】【坚持学习】【Day18】【ADO.NET 】
    【2016-11-2】【坚持学习】【Day17】【通过反射自动将datareader转为实体info】
    【2016-11-2】【坚持学习】【Day17】【微软 推出的SQLHelper】
  • 原文地址:https://www.cnblogs.com/wang9897/p/9484004.html
Copyright © 2011-2022 走看看