bzoj3110 K large data query

Posted by aboyd on Sun, 03 Nov 2019 12:35:47 +0100

Portal
When finding the KKK, mark the value greater than midmidmid mid as 1
If the number greater than or equal to midmidmidmidmid is marked as 1, it is possible that the largest KKK is midmidmidmid, and the number of 111 currently counted is greater than KKK (that is, there are multiple numbers of midmidmid midmidmid), so the answer will be raised (in order to reduce the number of 111).
That is to say, the answer range becomes [mid+1,r][mid+1,r][mid+1,r]. The answer was midmidmid mid. It's out of the pot.

For example: 3,4,4,4,5 find the third largest of 1 ~ 5. (obviously 4)
Assuming the current midmidmid is 4, the sequence becomes 0,1,1,1,1.
Because 4 & gt; 34 & gt; 34 > 3, the answer of dichotomy should be raised, and the answer should be locked in [mid+1,5][mid+1,5][mid+1,5]
So I got the wrong answer.

So mark the value greater than midmidmid midmid as 1.

50000 times add a number to 50000 locations. So the line tree counts sum burst int
Input negative number, pay attention to reading excellent

#include<bits/stdc++.h>
#define lc (root<<1)
#define rc (root<<1|1)
#define len(x) (T[x].r-T[x].l+1)
#define mid ((T[root].l+T[root].r)>>1)
#define ll long long
using namespace std;
const int maxn=5e4+10;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*f;
}
int n,m,op,a,b,c,cnt,ans[maxn];
struct que{int op,l,r,id;ll k;}Q[maxn],Q1[maxn],Q2[maxn];
struct node{int l,r;ll add,sum;}T[maxn<<2];
inline void pushup(int root){T[root].sum=T[lc].sum+T[rc].sum;}
inline void pushnow(int root,int val){
    T[root].add+=val;
    T[root].sum+=len(root)*val;
}
inline void pushdown(int root){
    if(T[root].add){
        pushnow(lc,T[root].add);
        pushnow(rc,T[root].add);
        T[root].add=0;
    }
}
inline void Update(int root,int l,int r,int val){
    if(l<=T[root].l&&T[root].r<=r)
        return pushnow(root,val);
    pushdown(root);
    if(l<=mid) Update(lc,l,r,val);
    if(r> mid) Update(rc,l,r,val);
    pushup(root);
}
inline ll Query(int root,int l,int r,ll ret=0){
    if(l<=T[root].l&&T[root].r<=r)
        return T[root].sum;
    pushdown(root);
    if(l<=mid) ret+=Query(lc,l,r);
    if(r> mid) ret+=Query(rc,l,r);
    return ret;
}
inline void build(int root,int l,int r){
    T[root].l=l,T[root].r=r;
    if(l==r) return;
    build(lc,l,mid),build(rc,mid+1,r);
}
inline void Solve(int l,int r,int S,int T){
    if(l>r||S>T) return;
    if(l==r){
        for(int i=S;i<=T;++i) if(Q[i].op==2)
            ans[Q[i].id]=l;
        return;
    }
    int Mid=(l+r)>>1,num1=0,num2=0;
    for(int i=S;i<=T;++i){
        if(Q[i].op==1){
            if(Q[i].k>Mid)
                Update(1,Q[i].l,Q[i].r,1),
                Q2[++num2]=Q[i];
            else Q1[++num1]=Q[i];
        }
        else{
            ll tmp=Query(1,Q[i].l,Q[i].r);
            if(tmp>=Q[i].k) Q2[++num2]=Q[i];
            else Q[i].k-=tmp,Q1[++num1]=Q[i];
        }
    }
    for(int i=1;i<=num2;++i) if(Q2[i].op==1) Update(1,Q2[i].l,Q2[i].r,-1);
    for(int i=1;i<=num1;++i) Q[S+i-1]=Q1[i];
    for(int i=1;i<=num2;++i) Q[S+num1+i-1]=Q2[i];
    Solve(l,Mid,S,S+num1-1),Solve(Mid+1,r,S+num1,T);
}
int main(){
    n=read(),m=read(),build(1,1,n);
    for(int i=1;i<=m;++i){
        Q[i].op=read(),Q[i].l=read(),Q[i].r=read(),Q[i].k=(ll)read();
        if(Q[i].op==2) Q[i].id=++cnt;
    }
    Solve(1,n,1,m);
    for(int i=1;i<=cnt;++i)
        printf("%d\n",ans[i]);
}