K大数查询

3110: [Zjoi2013]K大数查询

Time Limit: 20 Sec  Memory Limit: 512 MB

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

 分析:区间线段树套权值线段树;

    修改时就把对应权值范围内的线段树区间修改;

    查询时二分查询即可;

    看博客发现lazy不pushdown直接永久化标记会更快,orz;

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <climits>
#include <cstring>
#include <string>
#include <set>
#include <bitset>
#include <map>
#include <queue>
#include <stack>
#include <vector>
#define rep(i,m,n) for(i=m;i<=n;i++)
#define mod 1000000007
#define inf 0x3f3f3f3f
#define vi vector<int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ll long long
#define pi acos(-1.0)
#define pii pair<int,int>
#define sys system("pause")
const int maxn=5e4+10;
const int M=maxn*16*16;
using namespace std;
inline ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
inline ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p;p=p*p;q>>=1;}return f;}
inline int id(int l,int r){return l+r|l!=r;}
inline void umax(ll &p,ll q){if(p<q)p=q;}
inline void umin(ll &p,ll q){if(p>q)p=q;}
inline ll read()
{
    ll x=0;int f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,m,k,t,root[maxn*2],ls[M],rs[M],sz,num,L,R;
ll sum[M],lazy[M],a[maxn];
struct node
{
    int a,b,c;
    ll d;
}q[maxn];
void push_down(int l,int r,int k)
{
    int mid=l+r>>1;
    if(!ls[k])ls[k]=++sz;
    if(!rs[k])rs[k]=++sz;
    sum[ls[k]]+=lazy[k]*(mid-l+1);
    sum[rs[k]]+=lazy[k]*(r-mid);
    lazy[ls[k]]+=lazy[k],lazy[rs[k]]+=lazy[k];
    lazy[k]=0;
}
void push_up(int k){sum[k]=sum[ls[k]]+sum[rs[k]];}
void insert(int L,int R,int l,int r,int&k)
{
    if(!k)k=++sz;
    if(l==L&&r==R)
    {
        lazy[k]++;
        sum[k]+=r-l+1;
        return;
    }
    int mid=l+r>>1;
    if(lazy[k])push_down(l,r,k);
    if(R<=mid)insert(L,R,l,mid,ls[k]);
    else if(L>mid)insert(L,R,mid+1,r,rs[k]);
    else
    {
        insert(L,mid,l,mid,ls[k]);
        insert(mid+1,R,mid+1,r,rs[k]);
    }
    push_up(k);
}
ll cal(int L,int R,int l,int r,int k)
{
    if(l==L&&r==R)return sum[k];
    int mid=l+r>>1;
    if(lazy[k])push_down(l,r,k);
    if(R<=mid)return cal(L,R,l,mid,ls[k]);
    else if(L>mid)return cal(L,R,mid+1,r,rs[k]);
    else return cal(L,mid,l,mid,ls[k])+cal(mid+1,R,mid+1,r,rs[k]);
}
void add(int L,int R,int l,int r,int x)
{
    insert(L,R,1,n,root[id(l,r)]);
    if(l==r)return;
    int mid=l+r>>1;
    if(x<=mid)add(L,R,l,mid,x);
    else add(L,R,mid+1,r,x);
}
int gao(int L,int R,int l,int r,ll x)
{
    if(l==r)return l;
    int mid=l+r>>1;
    ll tmp;
    tmp=cal(L,R,1,n,root[id(mid+1,r)]);
    if(tmp>=x)return gao(L,R,mid+1,r,x);
    else return gao(L,R,l,mid,x-tmp);
}
int main()
{
    int i,j;
    scanf("%d%d",&n,&m);
    rep(i,1,m)
    {
        scanf("%d%d%d%lld",&q[i].a,&q[i].b,&q[i].c,&q[i].d);
        if(q[i].a==1)a[++num]=q[i].d;
    }
    sort(a+1,a+num+1);
    num=unique(a+1,a+num+1)-a-1;
    rep(i,1,m)
    {
        if(q[i].a==1)
        {
            q[i].d=lower_bound(a+1,a+num+1,q[i].d)-a;
            add(q[i].b,q[i].c,1,num,q[i].d);
        }
        else
        {
            printf("%lld\n",a[gao(q[i].b,q[i].c,1,num,q[i].d)]);
        }
    }
    return 0;
}
posted @ 2017-02-06 15:45  mxzf0213  阅读(331)  评论(0编辑  收藏  举报