[CQOI2015]任务查询系统(主席树)
Description
题目描述
最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分。
超级计算机中的任务用三元组 (s_i,e_i,p_i) 描述,(s_i,e_i,p_i) 表示任务从第 s_ii 秒开始,
在第 e_i 秒后结束(第 s_i 秒和 e_i 秒任务也在运行),其优先级为 p_i。同一时间可能有多个任务同时执行,
它们的优先级可能相同,也可能不同。调度系统会经常向查询系统询问,第 x_i 秒正在运行的任务中,
优先级最小的 k_i 个任务(即将任务按照优先级从小到大排序后取前 k_i 个)的优先级之和是多少。
特别的,如果 k_i 大于第 x_i秒正在运行的任务总数,则直接回答第 x_i 秒正在运行的任务优先级之和。
上述所有参数均为整数,时间的范围在 [1,n] 之间。
输入格式
输入文件第一行包含两个空格分开的正整数 m 和 n,分别表示任务总数和时间范围。接下来 m 行,
每行包含三个空格分开的正整数 s_i,e_i,p_i,(si≤ei)描述一个任务。接下来 n 行,
每行包含四个空格分开的整数 x_i,a_i,b_i,c_i,描述一次查询。
本题强制在线。
查询的参数 k_i 需要由公式ki=1+(ai×pre+bi)modci 计算得到。
其中 pre 表示上一次查询的结果,定义初始 pre=1 。
Solution
主席树模板???
对于每次开始和结束建一棵主席树,记录每个时间点最后建的一棵树的根编号
然后就是愉快的区间第k大查询模板
好久没这么顺地做一道数据结构啦
Code
#include <cstdio> #include <cstdlib> #include <algorithm> #include <vector> #define ll long long using namespace std; const int N=1e5+10; int n,m,p[N],cnt,tot,x,k,u,v; ll a,b,c,pre=1; ll re[N]; struct node { int v,id; bool operator <(const node &o)const { return v<o.v; } }d[N]; vector <int> s[N]; vector <int> t[N]; int rt[N],last; struct mode { int lc,rc,v; ll sum; }f[N*80]; void build(int l,int r,int &xx,int y,ll r_pos,int dd,int pos) { xx=++tot; f[xx]=f[y],f[xx].v+=dd; f[xx].sum+=r_pos; if(l==r) return ; int mid=(l+r)>>1; if(pos<=mid) build(l,mid,f[xx].lc,f[y].lc,r_pos,dd,pos); else build(mid+1,r,f[xx].rc,f[y].rc,r_pos,dd,pos); } ll get(int g,int l,int r,int k) { if(!g) return 0; if(f[g].v<=k) return f[g].sum; if(l==r) return re[l]*(ll)k; int mid=(l+r)>>1; if(k<=f[f[g].lc].v) return get(f[g].lc,l,mid,k); else return f[f[g].lc].sum+get(f[g].rc,mid+1,r,k-f[f[g].lc].v); } int main() { scanf("%d%d",&m,&n); for(int i=1;i<=m;i++) { scanf("%d%d%d",&u,&v,&d[i].v),d[i].id=i; s[u].push_back(i); t[v+1].push_back(i); } sort(d+1,d+1+m); for(int i=1;i<=m;i++) { if(i==1 || d[i].v!=d[i-1].v) re[++cnt]=d[i].v; p[d[i].id]=cnt; } for(int i=1;i<=n;i++) { int size=s[i].size(); for(int j=0;j<size;j++) build(1,cnt,rt[i],last,re[p[s[i][j]]],1,p[s[i][j]]),last=rt[i]; size=t[i].size(); for(int j=0;j<size;j++) build(1,cnt,rt[i],last,-re[p[t[i][j]]],-1,p[t[i][j]]),last=rt[i]; rt[i]=last; } while(n--) { scanf("%d%lld%lld%lld",&x,&a,&b,&c); k=1+(a*pre+b)%c; pre=get(rt[x],1,cnt,k); printf("%lld\n",pre); } return 0; }

浙公网安备 33010602011771号