P3168 题解
zhangbo1000 · · 题解
这题不一定要差分啊。
读完题不难想到覆盖了
直接取这两部分的交集是不好做的,考虑逆向:这一部分实际上就是所有任务减去在
“在
代码:(这里写的并非传统的可持久化线段树,细节见代码。)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<cstring>
#include<algorithm>
#include<queue>
#include<set>
#include<deque>
#include<map>
#include<random>
#include<unordered_map>
using namespace std;
namespace code{
using ll=long long;
using ull=unsigned long long;
using uint=unsigned int;
#define F(i,x,y) for(int i=(x),__tt2__=(y);i<=__tt2__;i++)
#define R(i,x,y) for(int i=(x),__tt2__=(y);i>=__tt2__;i--)
#define _F(i,x,y) for(int i=(x),__tt2__=(y);i<__tt2__;i++)
#define _R(i,x,y) for(int i=(x),__tt2__=(y);i>__tt2__;i--)
#define debug(x) cout<<#x<<'='<<(x)<<endl
constexpr int N=100005,M=10000005;
int c[N];
struct node{
ll tot;
int sum,cnt,ls,rs;
constexpr node(const ll& t=0,const int& s=0,const int& c=0,const int& l=0,const int& r=0):tot(t),sum(s),cnt(c),ls(l),rs(r){}
}tree[N*32];
int root1[N],root2[N],top=1;
#define newnode(x) (tree[++top]=tree[x],top)
void add(const int& ind,const int& x,const int& nl=1,const int& nr=N){
tree[ind].sum++;
tree[ind].tot+=c[x];
const int mid=(nl+nr)>>1;
if(x==mid)tree[ind].cnt++;
else if(x<mid){
tree[ind].ls=newnode(tree[ind].ls);
add(tree[ind].ls,x,nl,mid-1);
}
else {
tree[ind].rs=newnode(tree[ind].rs);
add(tree[ind].rs,x,mid+1,nr);
}
}
ll query(const int& k,const int& x1,const int& x2,const int& x3,const int& nl=1,const int& nr=N){
if(k==0)return 0;
const int mid=(nl+nr)>>1,lsum=tree[tree[x1].ls].sum-tree[tree[x2].ls].sum-tree[tree[x3].ls].sum;
const ll ltot=tree[tree[x1].ls].tot-tree[tree[x2].ls].tot-tree[tree[x3].ls].tot;
if(lsum>=k)return query(k,tree[x1].ls,tree[x2].ls,tree[x3].ls,nl,mid-1);
else if(lsum+tree[x1].cnt-tree[x2].cnt-tree[x3].cnt>=k){
return ltot+(k-lsum)*c[mid];
}
else return ltot+((ll)(c[mid]))*(tree[x1].cnt-tree[x2].cnt-tree[x3].cnt)+query(k-lsum-tree[x1].cnt+tree[x2].cnt+tree[x3].cnt,tree[x1].rs,tree[x2].rs,tree[x3].rs,mid+1,nr);
}
struct task{
int l,r,p;
constexpr task(const int& x=0,const int& y=0,const int& z=0):l(x),r(y),p(z){}
}a[N];
char tmp[100000],*p=0,*top1=0;
#define getchar() ((p==top1)&&(top1=(p=tmp)+fread(tmp,1,100000,stdin)),*p++)
void read(int& x){
char c;
while((c=getchar())<'0');
x=c^'0';
while((c=getchar())>='0')x=x*10+(c^'0');
}
int main(){
cin.tie(0)->sync_with_stdio(0);
int m,n;
read(m);
read(n);
F(i,1,m){
read(a[i].l);
read(a[i].r);
read(a[i].p);
c[i]=a[i].p;
}
sort(c+1,c+1+m);
F(i,1,m)a[i].p=lower_bound(c+1,c+1+m,a[i].p)-c;
sort(a+1,a+1+m,[](const task& x,const task& y)->bool{return x.r<y.r;});
for(int i=1,j=1;i<=n;i++){
root1[i]=newnode(root1[i-1]);
while(j<=m&&a[j].r<=i)add(root1[i],a[j++].p);
}
sort(a+1,a+1+m,[](const task& x,const task& y)->bool{return x.l<y.l;});
for(int i=n,j=m;i>=1;i--){
root2[i]=newnode(root2[i+1]);
while(j>=1&&a[j].l>=i)add(root2[i],a[j--].p);
}
ll last=1;
F(i,1,n){
int x,a,b,c;
read(x);
read(a);
read(b);
read(c);
int k=(((ll)(a))*last+b)%c+1;
if(k>tree[root1[n]].sum-tree[root1[x-1]].sum-tree[root2[x+1]].sum)
k=tree[root1[n]].sum-tree[root1[x-1]].sum-tree[root2[x+1]].sum;
printf("%lld\n",last=query(k,root1[n],root1[x-1],root2[x+1]));
}
return 0;
}
}
signed main(){return code::main();}