P3168 [CQOI2015]任务查询系统
题意
给出若干带有权值的区间, 每个区间可能相交或相离, 每个区间有三个属性(Si, Ei, Pi), 分别表示左端点,右端点,权值,其中端点范围属于[1, N]内;
随后有N条询问, 给出Xi, Ki, 令涉及到[1, Xi]区间中排名第Ki小的区间为A, 输出排名属于[1, K]时间点小于等于A的所有区间的权值和
Solution
- 将区间中权值的添加与删去用差分操作来表示
- 离散化端点, 权值
- 按时间线排序的差分操作建立主席树
- 于每条询问, 输出查询结果即可
需要注意的点
- 主席树的空间为 (最好多开1倍…)
- 注意离散化数值与权值之间不要混用
Code
#include<bits/stdc++.h>
#define reg register
const int maxn = 2e5 + 10;
int M;
int N;
int Len;
int cnt;
int Q_num;
int node_cnt;
int B[maxn<<2];
int rot[maxn*10];
int Apos[maxn<<2];
struct Cf{ int pos, val, opt; } A[maxn<<2];
struct Task{ int S, E, P; } ts[maxn<<2];
struct Node{ int lt, rt, val_sum, sum, cnt; } T[maxn*18];
bool cmp(Cf a, Cf b){ return a.pos < b.pos; }
void Add_node(int &now, int last, int l, int r, int val, int opt, int v){
T[now = ++ node_cnt] = T[last];
T[now].val_sum += opt * v;
T[now].sum += opt;
if(l == r) return ;
int mid = l+r >> 1;
if(val <= mid) Add_node(T[now].lt, T[last].lt, l, mid, val, opt, v);
else Add_node(T[now].rt, T[last].rt, mid+1, r, val, opt, v);
}
int Query(int rot, int k){
int lt = T[rot].lt, rt = T[rot].rt;
if(!lt && !rt) return T[rot].val_sum/T[rot].sum * k;
int lsum = T[lt].sum, rsum = T[rt].sum;
if(lsum >= k) return Query(lt, k);
return T[lt].val_sum + Query(rt, k - lsum);
}
int main(){
scanf("%d%d", &M, &Q_num);
for(reg int i = 1; i <= M; i ++){
scanf("%d%d%d", &ts[i].S, &ts[i].E, &ts[i].P);
A[++ cnt] = (Cf){ ts[i].S, ts[i].P, 1 };
A[++ cnt] = (Cf){ ts[i].E+1, ts[i].P, -1 }; // ts[i].E "+1"
B[++ N] = ts[i].P;
}
std::sort(A+1, A+cnt+1, cmp);
std::sort(B+1, B+N+1);
Len = std::unique(B+1, B+N+1) - B-1;
for(reg int i = 1; i <= cnt; i ++){
A[i].val = std::lower_bound(B+1, B+Len+1, A[i].val) - B;
Apos[i] = A[i].pos;
}
for(reg int i = 1; i <= cnt; i ++) Add_node(rot[i], rot[i-1], 1, Len, A[i].val, A[i].opt, B[A[i].val]);
int Pre_ans = 1;
for(reg int i = 1; i <= Q_num; i ++){
int Xi, Ai, Bi, Ci;
scanf("%d%d%d%d", &Xi, &Ai, &Bi, &Ci);
int Ki = 1 + (1ll*Ai*Pre_ans + Bi) % Ci;
int pos = std::upper_bound(Apos+1, Apos+cnt+1, Xi) - Apos-1;
if(Ki >= T[rot[pos]].sum) printf("%d
", Pre_ans=T[rot[pos]].val_sum);
else printf("%d
", Pre_ans=Query(rot[pos], Ki));
}
return 0;
}
//Do not confuse the 离散 and the origin value !
//Do remember the root[]'s size need to be large as the T[] !
//All arrays connected to Cf[] need to be large !