zoukankan      html  css  js  c++  java
  • BZOJ3110:[ZJOI2013]K大数查询——题解

    +++++++++++++++++++++++++++++++++++++++++++

    +本文作者:luyouqi233。               +

    +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

    +++++++++++++++++++++++++++++++++++++++++++

    http://www.lydsy.com/JudgeOnline/problem.php?id=3110

    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

    整体二分板子题,具体题解百度去吧,2333333……

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cctype>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    const int N=100010;
    inline ll read(){
        ll X=0,w=0;char ch=0;
        while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    int op[N],a[N],b[N],pos[N],ans[N];
    ll c[N],tree[2][N];
    int n,m,tot;
    int tmp1[N],tmp2[N];
    inline int lowbit(int t){return t&(-t);}
    void clear(int k,int x){
        for(int i=x;i<=tot;i+=lowbit(i))tree[k][i]=0;
    }
    void add(int k,int x,ll y){//将a[x]+y
        for(int i=x;i<=tot;i+=lowbit(i))tree[k][i]+=y;
    }
    void modify(ll x,ll y,ll z){
        add(0,x,z);add(1,x,z*(x-1));add(0,y+1,-z);add(1,y+1,-z*y);
    }
    ll query(int k,int x){//1-x区间和
        ll res=0;
        for(int i=x;i>0;i-=lowbit(i))res+=tree[k][i];
        return res;
    }
    ll qry(ll x,ll y){
        return query(0,y)*y-query(1,y)-query(0,x-1)*(x-1)+query(1,x-1);
    }
    void solve(int L,int R,int l,int r){
        if(L>R)return;
        if(l==r){
            for(int i=L;i<=R;i++){
                if(op[pos[i]]==2)ans[pos[i]]=l;
            }
            return;
        }
        int idx1=0,idx2=0,mid=(l+r)>>1;
        for(int i=L;i<=R;i++){
        if(op[pos[i]]==1){
            if((int)c[pos[i]]<=mid){
            modify(a[pos[i]],b[pos[i]],1);
            tmp1[idx1++]=pos[i];
            }else tmp2[idx2++]=pos[i];
        }else{
            ll tmp=qry(a[pos[i]],b[pos[i]]);
            if(tmp<c[pos[i]]){
            tmp2[idx2++]=pos[i];
            c[pos[i]]-=tmp;
            }
            else tmp1[idx1++]=pos[i];
        }
        }
        for(int i=0;i<idx1;i++){
        int k=tmp1[i];
        clear(0,a[k]);clear(1,a[k]);
        clear(0,b[k]+1);clear(1,b[k]+1);
        }
        int MID=L+idx1;
        for(int i=L;i<MID;i++)pos[i]=tmp1[i-L];
        for(int i=MID;i<=R;i++)pos[i]=tmp2[i-MID];
        solve(L,MID-1,l,mid);solve(MID,R,mid+1,r);
        return;
    }
    int main(){
        n=read(),m=read();
        for(int i=1;i<=m;i++){
        op[i]=read();
        a[i]=read();b[i]=read();c[i]=read();
        if(op[i]==1){c[i]=(ll)n-c[i]+1;tot=max(tot,(int)c[i]);}
        pos[i]=i;
        }
        solve(1,m,1,tot);
        for(int i=1;i<=m;i++){
        if(op[i]==2)printf("%d
    ",n-ans[i]+1);
        }
        return 0;
    }
  • 相关阅读:
    都不敢上CSDN了
    什么是函数(function)?
    今天3/8妇女节
    一件有意思的事情:关于std::string和std::auto_ptr
    转两篇Link相关的文章
    DevIL Downloads
    状态模式(State Pattern)
    访问者模式(Visitor Pattern)
    羊皮卷的故事第二章
    备忘录模式(Memento Pattern)
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/8279122.html
Copyright © 2011-2022 走看看