luogu P3168 [CQOI2015]任务查询系统
思路
又是强制在线--主席树
每一次操作建一棵树
但实际用的的rt只有n个
所以实际内存是n230
我见到只开n*30的,不会,
错误
debug
以为每一秒建立一颗树
第一次
query没有递归
第二、三次
权值线段树的查询处理,就是到叶子节点的处理
代码
// luogu-judger-enable-o2
#include <bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;++i)
#define ll long long
using namespace std;
const int maxn=2e5+7;
const int inf=0x3f3f3f3f;
int read() {
int x=0,f=1;char s=getchar();
for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
return x*f;
}
int n,m,lsh[maxn],rt[maxn],cnt;
struct edge {
int s,e,p;
}rw[maxn];
vector< pair<int,int> > add,del;
struct node {
int ch[2],siz;
ll sum;
}e[maxn*30];
void build(int &now,int old,int l,int r,int k,int pp) {
now=++cnt;
e[now]=e[old];
e[now].siz+=pp;
e[now].sum+=(ll)pp*lsh[k];
if(l==r) return;
int mid=(l+r)>>1;
if(k<=mid) build(e[now].ch[0],e[old].ch[0],l,mid,k,pp);
else build(e[now].ch[1],e[old].ch[1],mid+1,r,k,pp);
}
ll query(int now,int l,int r,int k) {
if(l==r) return k*lsh[l];
if(e[now].siz<=k) return e[now].sum;
int mid=(l+r)>>1;
if(e[e[now].ch[0]].siz>=k) return query(e[now].ch[0],l,mid,k);
else return e[e[now].ch[0]].sum+query(e[now].ch[1],mid+1,r,k-e[e[now].ch[0]].siz);
}
void debug(int now,int l,int r) {
if(l==r) {
if(e[now].siz!=0) cout<<l<<" ";
return;
}
int mid=(l+r)>>1;
debug(e[now].ch[0],l,mid);
debug(e[now].ch[1],mid+1,r);
}
int main() {
//read
n=read(),m=read();
FOR(i,1,n) {
rw[i].s=read(),rw[i].e=read(),rw[i].p=read();
lsh[i]=rw[i].p;
}
//lsh
sort(lsh+1,lsh+1+n);
int len=unique(lsh+1,lsh+1+n)-lsh-1;
FOR(i,1,n) rw[i].p=lower_bound(lsh+1,lsh+1+n,rw[i].p)-lsh;
//build
FOR(i,1,n) {
add.push_back(make_pair(rw[i].s,rw[i].p));
del.push_back(make_pair(rw[i].e+1,rw[i].p));
}
sort(add.begin(),add.end());
sort(del.begin(),del.end());
add.push_back(make_pair(inf,inf));
del.push_back(make_pair(inf,inf));
int ad=0,de=0;
int js=0;
FOR(i,1,n) {
int tmp=rt[i-1];
for(;add[ad].first==i;ad++) {
build(rt[i],tmp,1,len,add[ad].second,1);
tmp=rt[i];
}
for(;del[de].first==i;de++) {
build(rt[i],tmp,1,len,del[de].second,-1);
tmp=rt[i];
}
if(!rt[i]) rt[i]=rt[i-1];
}
//work
ll pre=1;
FOR(i,1,m) {
int id=read();
int a=read(),b=read(),c=read();
int k=(a*pre+b)%c+1;
if(k<=e[rt[id]].siz) pre=query(rt[id],1,len,k);
else pre=query(rt[id],1,len,e[rt[id]].siz);
cout<<pre<<"\n";
}
return 0;
}