P3168 [CQOI2015] 任务查询系统 题解
bloodstalk · · 题解
Description
有
Solution
给出一个不需要差分的主席树 + 二分的想法,应该更好想一点?
首先它要求前
查询的时候,我们先二分覆盖次数,找到
Code
#include<bits/stdc++.h>
//#define int long long
#define ll long long
#define next nxt
#define re register
#define il inline
const int N = 1e5 + 5;
using namespace std;
int max(int x,int y){return x > y ? x : y;}
int min(int x,int y){return x < y ? x : y;}
int m,n,sec,ai,bi,ci,ki;
ll ans;
int root[N],idx;
struct Mission{
int s,e,p;
bool operator < (Mission &t) { return p < t.p; }
}a[N];
struct Tree{
int l,r,siz;//覆盖次数
ll sum;//覆盖权值
}tree[N*100];
il int read()
{
int f=0,s=0;
char ch=getchar();
for(;!isdigit(ch);ch=getchar()) f |= (ch=='-');
for(; isdigit(ch);ch=getchar()) s = (s<<1) + (s<<3) + (ch^48);
return f ? -s : s;
}
#define lc(x) tree[x].l
#define rc(x) tree[x].r
il void Modify(int x,int &y,int l,int r,int nl,int nr,int k)
{
y = ++idx;
tree[y] = tree[x];
if(nl <= l && r <= nr)
{
tree[y].sum += k , tree[y].siz++;//被完全覆盖的打上标记即可
return ;
}
int mid = (l+r) >> 1;
if(nl <= mid) Modify(lc(x),lc(y),l,mid,nl,nr,k);
if(nr > mid) Modify(rc(x),rc(y),mid+1,r,nl,nr,k);
}
il int QueryCnt(int p,int l,int r,int pos,int tag)//tag就是一路处理标记
{
int res = 0;
if(l == pos && r == pos) return tree[p].siz + tag;//叶子节点
int mid = (l+r) >> 1;
if(pos <= mid) res = QueryCnt(lc(p),l,mid,pos,tag+tree[p].siz);
if(pos > mid) res = QueryCnt(rc(p),mid+1,r,pos,tag+tree[p].siz);
return res;
}
il ll QuerySum(int p,int l,int r,int pos,ll tag)
{
ll res = 0;
if(l == pos && r == pos) return tree[p].sum + tag;
int mid = (l+r) >> 1;
if(pos <= mid) res = QuerySum(lc(p),l,mid,pos,tag+tree[p].sum);
if(pos > mid) res = QuerySum(rc(p),mid+1,r,pos,tag+tree[p].sum);
return res;
}
il ll Um_nik(int x,int k)//第x秒被覆盖k次
{
int l = 1 , r = m , tot = m+1;
if(k >= m) return QuerySum(root[m],1,n,x,0);
while(l <= r)//二分被覆盖次数
{
int mid = (l+r) >> 1;
if(QueryCnt(root[mid],1,n,x,0) <= k) tot = mid , l = mid + 1;
else r = mid - 1;
}
return QuerySum(root[tot],1,n,x,0);//返回那个版本的被覆盖权值
}
signed main()
{
m = read() , n = read();
for(re int i=1;i<=m;i++) a[i].s = read() , a[i].e = read() , a[i].p = read();
sort(a+1,a+m+1);//按照权值排序
for(re int i=1;i<=m;i++) Modify(root[i-1],root[i],1,n,a[i].s,a[i].e,a[i].p);//建立版本
ans = 1;
for(re int i=1;i<=n;i++)
{
sec = read() , ai = read() , bi = read() , ci = read();
ki = 1ll * ((ans % ci * ai % ci + bi % ci) % ci + 1);
ans = Um_nik(sec,ki);
cout << ans << "\n";
}
return 0;
}