首页 > 代码库 > BZOJ3932(主席树上二分+差分

BZOJ3932(主席树上二分+差分

按时间作为主席树的版本,每个版本的主席树都是一个权值线段树。

差分消去时间影响

对于当前时间版本的主席树查询前K大即可。

树上二分时结束后切记判定l==r的状态(易错

l==r叶子节点可能存在多个值(值大小为sum/siz )

用I64dOLE了好久 。。 。。。。 。 。。 。 。 。 。 。 。 。 。。 。 

用bit/stdc++.h  CE.....

技术分享
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 301500;
const int LOGN = 35;
const int maxn = N*LOGN;
#define lson son[rt][0]
#define rson son[rt][1]
#define un(x) (x>0?x:-x)
struct node{
    int pos,val;
};
node cf[N<<1];
ll sum[maxn],siz[maxn];
int son[maxn][2],root[N],id[N];
void pushup(int rt)
{
    siz[rt] = siz[lson]+siz[rson];
    sum[rt] = sum[lson]+sum[rson];
}
int tot = 0;
void update(int x,int& y,int l,int r,int p)
{
    y = ++tot;
    if(l==r)
    {
        if(p>0) siz[y] = siz[x]+1;
        else siz[y] = siz[x]-1;
        sum[y] = sum[x]+p;
        return ;
    }
    son[y][0] = son[x][0];
    son[y][1] = son[x][1];
    int m = (r+l)>>1;
    if(un(p)<=m) update(son[x][0],son[y][0],l,m,p);
    else update(son[x][1],son[y][1],m+1,r,p);
    pushup(y);

}
ll  bfind(int l,int r,int rt,int k)
{
    //cout<<"size:: "<<siz[rt]<<sum[rt]<<endl;
    if(siz[rt]<=k) return sum[rt];
    ll ans = 0;
    while(l<r)
    {
        int m = (r+l)>>1;
        if(k<siz[lson])
        {
            r = m;
            rt = lson;
        }
        else{
            l = m+1;
            k -= siz[lson];
            ans+=sum[lson];
            rt = rson;
        }
    }
    if(k&&siz[rt]>0) ans+=sum[rt]/siz[rt]*min(k,siz[rt]);
    return ans;
}
bool cmp(node a,node b)
{
    return a.pos<b.pos;
}
int main()
{
    int n,m;
    scanf("%d%d",&m,&n);
    int s,e,p;
    int lim = 0;
    int cnt = 0;
    for(int i=0;i<m;i++){
        scanf("%d%d%d",&s,&e,&p);
        cf[++cnt] = (node){s,p};
        cf[++cnt] = (node){e+1,-p};
        lim = max(lim,p);
    }
    sort(cf+1,cf+cnt+1,cmp);
    ll pre = 1;
    for(int i=1;i<=cnt;i++)update(root[i-1],root[i],1,lim,cf[i].val);
    for(int i=cnt;i>=1;i--){
        if(cf[i].pos!=cf[i+1].pos) id[cf[i].pos] = i;
    }
    for(int i=1;i<=n;i++){
        if(id[i]==0)id[i] = id[i-1];
        //cout<<id[i]<<endl;
    }
    int x,a,b,c,k;
    for(int i=0;i<n;i++)
    {
        scanf("%d%d%d%d",&x,&a,&b,&c);
        k = (a*pre+b)%c+1;
        pre = bfind(1,lim,root[id[x]],k);
        //cout<<x<<"  "<<id[x]<<" ";
        printf("%lld\n",pre);
    }
    return 0;
}
AC代码

 

BZOJ3932(主席树上二分+差分