hdu 4866/bzoj 3932 Shooting/任务查询系统(主席树)

题意:

     有n条平行于x轴的线段,m次射击,每次射击射中前k个线段,得到的分数为 i = 1 k d i 其中 d i 为线段到x轴距离,k为 ( a p r e + b ) mod c ,pre为上次得分,并且如果pre大于p,那么本次得分翻倍

思路:

    主席树处理出的是一个前缀和,而利用差分,就能很好的染出一片区域。意思就是,对于每条线段,我们在 l + d ,在 r + 1 d ,然后我们对于每一个x坐标建立一棵线段树,这样就能产生一颗主席树。我们可以发现,这样的树,可以维护每个x轴坐标上的线段情况,我们维护num和sum两个数组,一个记录此时下面有几个点,一个维护分数和,在每次射击的时候,利用数量向下走即可
    注意,可能出现线段重合的情况,这时候需要加一些判断

    更新:和任务查询系统一模一样。。。

错误及反思:

代码:

#include<bits/stdc++.h>
using namespace std;
#define lson l,m
#define rson m+1,r
#define fi first
#define se second
const int N = 200010;

int ls[N*30],rs[N*30],num[N*30],n,m,x,p,cnt,root[N];
long long sum[N*30];

vector<int> v;
struct LINE{
    int l,r,d;
}line[N];

vector<pair<int,int> > need[N];

int getid(int x){return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}

void init(){
    cnt=0;
    v.clear();
}

int build(int l,int r){
    int rt=++cnt;
    ls[rt]=rt; rs[rt]=rt; sum[rt]=0; num[rt]=0;
    if(l==r) return rt;
    int m=l+r>>1;
    ls[rt]=build(lson);
    rs[rt]=build(rson);
    return rt;
}

int update(int pre,int val,int pos,int l,int r){
    int rt=++cnt;
    sum[rt]=sum[pre]+val; ls[rt]=ls[pre]; rs[rt]=rs[pre]; num[rt]=num[pre]+(val>0?1:-1);
    if(l==r) return rt;
    int m=l+r>>1;
    if(m>=pos) ls[rt]=update(ls[pre],val,pos,lson);
    else rs[rt]=update(rs[pre],val,pos,rson);
    return rt;
}

long long query(int r2,int k,int l,int r){
    if(l==r){
        if(num[r2]==0) return 0;
        if(num[r2]>=k)
            return sum[r2]/num[r2]*k;
        return sum[r2];
    }
    int m=l+r>>1;
    if(num[ls[r2]]>=k) return query(ls[r2],k,lson);
    return sum[ls[r2]]+query(rs[r2],k-num[ls[r2]],rson);
}

int main(){
    while(scanf("%d%d%d%d",&n,&m,&x,&p)!=EOF){
        init();
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&line[i].l,&line[i].r,&line[i].d);
            v.push_back(line[i].d);
        }
        sort(v.begin(),v.end()),v.erase(unique(v.begin(),v.end()),v.end());

        for(int i=1;i<=n;i++){
            need[line[i].l].push_back({getid(line[i].d),line[i].d});
            need[line[i].r+1].push_back({getid(line[i].d),-line[i].d});
        }

        root[0]=build(1,v.size());
        for(int i=1;i<=x;i++){
            int bef=root[i-1];
            for(int j=0;j<need[i].size();j++){
                bef=update(bef,need[i][j].se,need[i][j].fi,1,v.size());
            }
            root[i]=bef;
        }
        long long pre=1;
        while(m--){
            int xx,a,b,c;
            scanf("%d%d%d%d",&xx,&a,&b,&c);
            long long k=(1ll*a*pre+b)%c;
            k=query(root[xx],(int)k,1,v.size());
            if(pre>p) k*=2;
            pre=k;
            printf("%lld\n",pre);
        }
        for(int i=1;i<=x+1;i++) need[i].clear();
    }
}

猜你喜欢

转载自blog.csdn.net/roll_keyboard/article/details/80668041