HDU 4866 Shooting 二分+主席树

直接用主席树维护下分数和个数就行了,思路挺好想的,不过比赛的时候我死活都没往主席树上想。。。唉。。。

然后需要注意的地方是,

1,区间更新时需要标记永久化,也就是标记不下放。

2,开64倍空间。一般开结构体会多用一些空间,所以空间比较紧的时候可以改成数组。

最后说说坑点,RE返回T。。。不过开64倍空间是最稳妥的。

#pragma comment(linker,"/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define MS0(a) memset(a,0,sizeof(a))

using namespace std;

typedef long long ll;
const int maxn=100010;
const int INF=1e9+10;

int N,M,X;ll P;
int L,R,D;
int x,a,b,c,K;

struct Query
{
    ll pts;int cnt;
    friend Query operator+(Query A,Query B)
    {
        return (Query){A.pts+B.pts,A.cnt+B.cnt};
    }
};

int ls[maxn*64],rs[maxn*64];
ll pts[maxn*64];
int cnt[maxn*64];
int tot;
int rt[maxn];

int build(int l,int r)
{
    int k=++tot;
    pts[k]=cnt[k]=0;
    ls[k]=rs[k]=-1;
    if(l==r) return k;
    int m=(l+r)>>1;
    ls[k]=build(l,m);
    rs[k]=build(m+1,r);
    return k;
}

int update(int L,int R,ll D,int l,int r,int x)
{
    int k=++tot;
    pts[k]=pts[x];cnt[k]=cnt[x];
    ls[k]=ls[x];rs[k]=rs[x];
    if(L<=l&&r<=R){
        pts[k]+=D;
        cnt[k]++;
        return k;
    }
    int m=(l+r)>>1;
    if(L<=m) ls[k]=update(L,R,D,l,m,ls[k]);
    if(R>m) rs[k]=update(L,R,D,m+1,r,rs[k]);
    return k;
}

Query query(int p,int l,int r,int k)
{
    Query res={pts[k],cnt[k]};
    if(l==r) return res;
    int m=(l+r)>>1;
    if(p<=m) return res+query(p,l,m,ls[k]);
    else return res+query(p,m+1,r,rs[k]);
}

struct Target
{
    int L,R,D;
    friend bool operator<(Target A,Target B)
    {
        return A.D<B.D;
    }
    void read()
    {
        scanf("%d%d%d",&L,&R,&D);
    }
};Target target[maxn];

ll bin(int l,int r,int x,int K)
{
    ll res=0;
    while(l<=r){
        int m=(l+r)>>1;
        Query tmp=query(x,1,X,rt[m]);
        if(tmp.cnt<=K) l=m+1,res=max(res,tmp.pts);
        else r=m-1;
    }
    return res;
}

void debug(int k,int l,int r)
{
    if(k==-1) return;
    printf("l=%2d r=%2d ",l,r);
    //tr[k].out();
    int m=(l+r)>>1;
    debug(ls[k],l,m);
    debug(rs[k],m+1,r);
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif // ONLINE_JUDGE
    while(~scanf("%d%d%d%I64d",&N,&M,&X,&P)){
        REP(i,1,N) target[i].read();
        sort(target+1,target+N+1);
        tot=0;
        rt[0]=build(1,X);
        REP(i,1,N){
            L=target[i].L,R=target[i].R,D=target[i].D;
            rt[i]=update(L,R,D,1,X,rt[i-1]);
        }
        ll res=1,pre=1;
        REP(i,1,M){
            scanf("%d%d%d%d",&x,&a,&b,&c);
            K=(1LL*a*pre+b)%c;
            res=bin(0,N,x,K);
            if(pre>P) res*=2;
            printf("%I64d
",pre=res);
        }
    }
    return 0;
}
View Code
没有AC不了的题,只有不努力的ACMER!
原文地址:https://www.cnblogs.com/--560/p/5277429.html