您的位置:首页 > 其它

BZOJ 3932: [CQOI2015]任务查询系统 [主席树]

2018-01-11 14:46 435 查看

题意

给出n个由三元组(si,ei,pi)表示的区间,si,ei表示头尾(包括头尾),pi表示这个区间的权重

给出m个询问,询问包含位置x的按权重排序前k小的区间的权重和

输入先给出所有三元组,询问强制在线

题解

主席树的权值线段树按照pi来搞,因为值域比较大,要离散一下

所有三元组先读入,拆成两个端点

每个端点维护两个权值,sum1表示权重和,sum2表示区间个数

s和e+1,s上为正的,e+1上为负的,相当于差分

然后把每个端点按时间轴插入主席树

注意下空间

#include<cstdio>
#include<algorithm>
#define N 100005
#define M N*40
#define LL long long
using namespace std;

int n,m,sz,ls[M],rs[M],P
,pos
,id
,root
;
LL tmp,sum1[M],sum2[M];
struct node{
int tim,pos,v1,v2;
}a[N<<1];

inline int read(){
int a=0;char f=1,c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){a=a*10+c-'0';c=getchar();}
return a*f;
}

inline bool cmp(int x,int y){return P[x]<P[y];}

inline bool cmp1(node x,node y){return x.tim<y.tim;}

void insert(int &x,int l,int r,int lst,int p,int v1,int v2){
x=++sz;
ls[x]=ls[lst],rs[x]=rs[lst];
sum1[x]=sum1[lst]+v1,sum2[x]=sum2[lst]+v2;
if(l==r) return;
int mid=l+r>>1;
if(p<=mid) insert(ls[x],l,mid,ls[lst],p,v1,v2);
else insert(rs[x],mid+1,r,rs[lst],p,v1,v2);
return;
}

LL query(int x,int l,int r,int k){
if(l==r) return sum1[x]+tmp;
int mid=l+r>>1,cnt=sum2[ls[x]];
if(cnt>=k) return query(ls[x],l,mid,k);
else{
tmp+=sum1[ls[x]];
return query(rs[x],mid+1,r,k-cnt);
}
}

int main(){
freopen("testdata.in","r",stdin);
//  freopen("testdata.out","w",stdout);
n=read(),m=read();
int i,j;
for(i=1,sz=0;i<=n;++i){
int s=read(),t=read()+1;P[i]=read();
a[++sz].tim=s,a[sz].v1=P[i],a[sz].v2=1;
a[++sz].tim=t,a[sz].v1=-P[i],a[sz].v2=-1;
id[i]=i;
}
sort(id+1,id+n+1,cmp);
for(i=1;i<=n;++i) pos[id[i]]=i;
for(i=1,sz=0;i<=n;++i) a[++sz].pos=pos[i],a[++sz].pos=pos[i];
sort(a+1,a+sz+1,cmp1);
sz=0;
for(i=1,j=1;i<=m;++i){
root[i]=root[i-1];
while(a[j].tim==i){
insert(root[i],1,n,root[i],a[j].pos,a[j].v1,a[j].v2);
++j;
}
}
LL ans=1,A,B,C,K,x;
while(m--){
x=read(),A=read(),B=read(),C=read();
K=1+(A*ans+B)%C;
tmp=0;
ans=query(root[x],1,n,K);
printf("%lld\n",ans);
}
return 0;
}


为什么我总是跑得这么慢啊
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: