HDU 4866 Shooting 扫描线+主席树

来源:互联网 发布:origin数据表转换矩阵 编辑:程序博客网 时间:2024/06/06 19:21

题意是求x点上面到坐标轴前k小的距离之和。

因为x只有100000所以直接扫x至于线段我们可以用vector分别存线段起点和终点,对于扫到p的时候,把以p为起点的线段加入主席树,把p-1位终点的线段拿出主席树,然后就是简单询问。

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<vector>using namespace std;const int maxn=100005;int a[maxn],root[maxn],tot;vector<int >g[maxn],g1[maxn];typedef long long LL;struct pi{    LL sum1;    int sum;    int lson;    int rson;}pp[maxn*20*3];struct ppi{    int a,b,x;}pp1[maxn];void build(int cnt,int l,int r){    pp[cnt].sum=0;    pp[cnt].sum1=0;    if(l==r) return ;    pp[cnt].lson=++tot;    build(tot,l,(l+r)/2);    pp[cnt].rson=++tot;    build(tot,(l+r)/2+1,r);}void merg(int qq,int cnt,int n,int p,int k,int k1){    int le,ri,mid;    le=1;    ri=n;    while(le<=ri){        pp[cnt]=pp[qq];        pp[cnt].sum+=k;        pp[cnt].sum1+=k1;        mid=(le+ri)/2;        if(le==ri) return ;        if(p<=mid){            pp[cnt].lson=++tot;            cnt=tot;            qq=pp[qq].lson;            ri=mid;        }        else{            pp[cnt].rson=++tot;            cnt=tot;            qq=pp[qq].rson;            le=mid+1;        }    }}int query(int cnt,int le,int ri,int l,int r){    if(l>r) return 0;    if(le>=l&&ri<=r){        return pp[cnt].sum;    }    int s=0,mid;    mid=(le+ri)/2;    if(l<=mid) s+=query(pp[cnt].lson,le,mid,l,r);    if(r>mid) s+=query(pp[cnt].rson,mid+1,ri,l,r);    return s;}LL query1(int cnt,int le,int ri,int l,int r){    if(l>r) return 0;    if(le>=l&&ri<=r) return pp[cnt].sum1;    LL s=0;    int mid=(le+ri)/2;    if(l<=mid) s+=query1(pp[cnt].lson,le,mid,l,r);    if(r>mid) s+=query1(pp[cnt].rson,mid+1,ri,l,r);    return s;}int get(int cnt,int n,int k){    int le=1,ri=n,mid;    int p=query(cnt,1,n,1,n);    if(p<k){        k=p;    }    while(le<=ri){        mid=(le+ri)/2;        if(query(cnt,1,n,1,mid)>=k) ri=mid-1;        else le=mid+1;    }    return le;}int main(){    int i,j,n,m,x,ppp,aa,b,c;    LL k;    while(cin>>n>>m>>x>>ppp){        for(i=1;i<=x+1;i++){            g[i].clear();            g1[i].clear();        }        tot=0;        root[0]=0;        tot++;        build(0,1,n);        for(i=1;i<=n;i++){            scanf("%d%d%d",&pp1[i].a,&pp1[i].b,&pp1[i].x);            g[pp1[i].a].push_back(i);            g1[pp1[i].b+1].push_back(i);            a[i]=pp1[i].x;        }        sort(a+1,a+1+n);        for(i=1;i<=n;i++){            pp1[i].x=lower_bound(a+1,a+1+n,pp1[i].x)-a;        }        int q;        for(i=1;i<=x;i++){            q=root[i-1];            int p=g[i].size();            for(j=0;j<p;j++){                root[i]=++tot;                merg(q,tot,n,pp1[g[i][j]].x,1,a[pp1[g[i][j]].x]);                q=root[i];            }            int w=g1[i].size();            for(j=0;j<w;j++){                root[i]=++tot;                merg(q,tot,n,pp1[g1[i][j]].x,-1,-a[pp1[g1[i][j]].x]);                q=root[i];            }            if(q==root[i-1]){                root[i]=++tot;                pp[root[i]]=pp[root[i-1]];            }        }        LL pre;        pre=1;        for(i=0;i<m;i++){            scanf("%d%d%d%d",&x,&aa,&b,&c);            k=((LL)aa*pre%c+b)%c;            if(k==0){                printf("0\n");                pre=0;                continue;            }            int p=get(root[x],n,k);            LL qq;            int xx=query(root[x], 1, n,1,p-1);            qq=query1(root[x],1,n,1,p-1);            qq+=(k-xx)*a[p];            if(pre>ppp) qq=qq*2;            printf("%lld\n",qq);            pre=qq;        }    }}


0 0
原创粉丝点击