您的位置:首页 > 其它

BZOJ3932: [CQOI2015]任务查询系统

2017-03-31 20:01 309 查看
BZOJ3932

差分+主席树。

做了好几天。。今天实在调不下去了就去看了看别人的代码。。

实现上还是不够老练。。

Query里返回sum[x]/sz[x]∗(ll)y还是想了半天。其实是因为,每个值在一个区间里可能出现多次,所以查询到l==r时,可能y不为1,所以这样处理。

【代码】

#include <cstdio>
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#define N 100005
#define M 22000005
#define INF 1e9
#define mod 1000000007
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pa;

int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}

ll sum[M],Last_Ans=1;
int n,m,tot,cnt,tt;
int a
,num[N<<1];
int ls[M],rs[M],sz[M],root
;
int s
,e
,p
;

class Add{
public:
int x,z,w;
Add(){}
Add(int xx,int zz,int ww)
{x=xx,z=zz,w=ww;}
}E[N<<1];

bool operator <(Add a,Add b){
return a.x<b.x;
}

int lowbit(int x){
return x&-x;
}

int Find(int x)
{
int l=1,r=tot,rtn;
while(l<=r)
{
int mid=l+r>>1;
if(num[mid]>=x) rtn=mid,r=mid-1;
else l=mid+1;
}
return rtn;
}

void Build(int &k,int l,int r)
{
k=++cnt;
if(l==r) return;
int mid=l+r>>1;
Build(ls[k],l,mid);Build(rs[k],mid+1,r);
}

void Update(int l,int r,int x,int &y,int z,int w)
{
y=++cnt;
sz[y]=sz[x]+w;sum[y]=sum[x]+num[z]*w;
if(l==r) return;
ls[y]=ls[x];rs[y]=rs[x];
int mid=l+r>>1;
if(z<=mid) Update(l,mid,ls[x],ls[y],z,w);
else Update(mid+1,r,rs[x],rs[y],z,w);
}

void Input_Init()
{
n=read(),m=read();
for(int i=1;i<=n;i++) s[i]=read(),e[i]=read(),num[i]=p[i]=read();
sort(num+1,num+1+n);
tot=unique(num+1,num+1+n)-num-1;
for(int i=1;i<=n;i++)
{
E[++tt]=(Add){s[i],Find(p[i]),1};
E[++tt]=(Add){e[i]+1,Find(p[i]),-1};
}
sort(E+1,E+1+tt);
Build(root[0],1,m);
for(int i=1,j=1;i<=m;i++)
{
root[i]=root[i-1];
for(;j<=tt&&E[j].x==i;j++)
Update(1,tot,root[i],root[i],E[j].z,E[j].w);
}
}

ll Query(int l,int r,int x,int y)
{
if(l==r) return sum[x]/sz[x]*(ll)y;
int mid=l+r>>1;
if(sz[ls[x]]>=y) return Query(l,mid,ls[x],y);
return sum[ls[x]]+Query(mid+1,r,rs[x],y-sz[ls[x]]);
}

void Solve()
{
for(int i=1;i<=m;i++)
{
static int x,a,b,c;
x=read(),a=read(),b=read(),c=read();
int k=((ll)a*Last_Ans+b)%c+1;
if(k>sz[root[x]]) Last_Ans=sum[root[x]];
else Last_Ans=Query(1,tot,root[x],k);
printf("%lld\n",Last_Ans);
}
}

int main()
{
Input_Init();
Solve();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: