[bzoj3932][CQOI2015]任务查询系统-题解[主席树][权值线段树]
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[bzoj3932][CQOI2015]任务查询系统-题解[主席树][权值线段树]相关的知识,希望对你有一定的参考价值。
Description
最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分。超级计算机中的
任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第Ei秒后结束(第Si秒和Ei秒任务也在运行
),其优先级为Pi。同一时间可能有多个任务同时执行,它们的优先级可能相同,也可能不同。调度系统会经常向
查询系统询问,第Xi秒正在运行的任务中,优先级最小的Ki个任务(即将任务按照优先级从小到大排序后取前Ki个
)的优先级之和是多少。特别的,如果Ki大于第Xi秒正在运行的任务总数,则直接回答第Xi秒正在运行的任务优先
级之和。上述所有参数均为整数,时间的范围在1到n之间(包含1和n)。
Input
输入文件第一行包含两个空格分开的正整数m和n,分别表示任务总数和时间范围。接下来m行,每行包含三个空格
分开的正整数Si、Ei和Pi(Si≤Ei),描述一个任务。接下来n行,每行包含四个空格分开的整数Xi、Ai、Bi和Ci,
描述一次查询。查询的参数Ki需要由公式 Ki=1+(Ai*Pre+Bi) mod Ci计算得到。其中Pre表示上一次查询的结果,
对于第一次查询,Pre=1。
Output
输出共n行,每行一个整数,表示查询结果。
Sample Input
4 3
1 2 6
2 3 3
1 3 2
3 3 4
3 1 3 2
1 1 3 4
2 2 4 3
1 2 6
2 3 3
1 3 2
3 3 4
3 1 3 2
1 1 3 4
2 2 4 3
Sample Output
2
8
11
8
11
HINT
样例解释
K1 = (1*1+3)%2+1 = 1
K2 = (1*2+3)%4+1 = 2
K3 = (2*8+4)%3+1 = 3
对于100%的数据,1≤m,n,Si,Ei,Ci≤100000,0≤Ai,Bi≤100000,1≤Pi≤10000000,Xi为1到n的一个排列
正在学主席树。。听说这个题是个模板题就跑去做了。。
如果你不知道什么是主席树的话建议出门左转去学。。
对于每一个时间点我们建一个版本的权值线段树,每个线段树记录当前结点的任务数与这个结点的任务优先级之和。
一个任务从i到j的话就给第i个版本++,第j+1个版本--;
但是我们需要考虑几个事情
1.pi太大,需要离散化,这是很显然的。
2.修改了第x个版本的话后面所有版本都需要更改。
对于1我的方法是把所有优先级先序排序去重然后依次放到数组里,因为排了序了所以它们的大小关系不会改变,然后通过二分找到离散化以后的值(但是被dalao嘲讽了)
对于2我的方法是把所有操作按时间点大小先序排序,然后依次进行操作,如果当前的操作点比目前建的树要大那就开到那个时间点
这个意思
1 for(int i=1;i<=操作数;++i) 2 { 3 while(已经建了p个<a[i].time){建树(++p);} 4 操作:加或减 5 }
因为我之后建的树会复制前面的树的值,而前面的树的操作都是已经做完了的,然后这个操作是2*m+n。
当然这个也被dalao嘲讽了。。
然后有一个东西要考虑(我就是错了这个)
就是你查询到叶子结点的时候,它的任务数可能会比你剩下要查的个数要大,这样你就不需要取走全部了。。似乎是一个很显然的事情但我当时做却没想到。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #define N (100000+5) 7 #define ll long long 8 using namespace std; 9 inline ll read() 10 { 11 char ch=getchar();ll kin=1,gi=0; 12 while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)kin=-1;ch=getchar();} 13 while(ch>=‘0‘&&ch<=‘9‘){gi=gi*10+ch-48;ch=getchar();} 14 return kin*gi; 15 } 16 struct tree 17 { 18 ll num; 19 ll simple; 20 ll son[2]; 21 ll l,r,fl; 22 }d[5000005]; 23 struct naive 24 { 25 ll nic; 26 ll st; 27 bool fl; 28 }ni[N*2]; 29 bool cmp(naive x,naive y) 30 { 31 return x.st<y.st; 32 } 33 ll n,m,siz,rt[N]; 34 ll sot[N],trl[N],kiz,fis,trik; 35 ll pre=1,lis[N],ra,rig; 36 void make(ll,ll,bool); 37 ll query(ll,ll); 38 void build(ll,ll,ll); 39 void rut(ll); 40 ll mmid(ll x) 41 { 42 ll l=1,r=kiz,res=0; 43 while(l<=r) 44 { 45 ll mid=(l+r)>>1; 46 if(trl[mid]<=x){l=mid+1;res=mid;} 47 else r=mid-1; 48 } 49 return res; 50 } 51 int main() 52 { 53 m=read();n=read(); 54 for(ll i=1;i<=m;++i) 55 { 56 57 ni[++trik].st=read();ni[trik].fl=1; 58 ni[++trik].st=read()+1;ni[trik].fl=0; 59 ni[trik-1].nic=ni[trik].nic=read(); 60 sot[i]=ni[trik].nic; 61 } 62 sort(sot+1,sot+m+1); 63 sort(ni+1,ni+trik+1,cmp); 64 for(ll i=1;i<=m;++i)if(sot[i]!=sot[i-1])trl[++kiz]=sot[i]; 65 for(ll i=1;i<=trik;++i) 66 { 67 if(ni[i].st>n)break; 68 while(fis<ni[i].st){rut(++fis);} 69 ll rik=mmid(ni[i].nic); 70 make(ni[i].st,rik,ni[i].fl); 71 } 72 while(fis<n){rut(++fis);} 73 for(ll i=1;i<=n;++i) 74 { 75 ll sec=read(); 76 ll a,b,c,k; 77 a=read();b=read();c=read(); 78 k=(a*pre+b)%c+1; 79 printf("%lld\\n",pre=query(sec,k)); 80 } 81 return 0; 82 } 83 ll query(ll x,ll y) 84 { 85 ll nw=rt[x],res=0; 86 y=min(y,d[nw].simple); 87 while(1) 88 { 89 if(y==0)break; 90 if(d[nw].l==d[nw].r&&d[nw].simple>y){res+=trl[d[nw].l]*y;break;} 91 if(d[nw].simple<=y){res+=d[nw].num;break;} 92 if(d[d[nw].son[0]].simple<=y) y-=d[d[nw].son[0]].simple,res+=d[d[nw].son[0]].num,nw=d[nw].son[1]; 93 else nw=d[nw].son[0]; 94 } 95 return res; 96 } 97 void make(ll x,ll num,bool p) 98 { 99 ll nw=rt[x];bool f; 100 while(d[nw].l!=d[nw].r) 101 { 102 if(p) 103 {d[nw].num+=trl[num];d[nw].simple++;} 104 else 105 {d[nw].num-=trl[num];d[nw].simple--;} 106 f=(num>(d[nw].l+d[nw].r)>>1); 107 if(d[d[nw].son[f]].fl!=x) 108 { 109 d[++siz]=d[d[nw].son[f]]; 110 d[nw].son[f]=siz; 111 d[siz].fl=x; 112 } 113 nw=d[nw].son[f]; 114 } 115 if(p) 116 {d[nw].num+=trl[num];d[nw].simple++;} 117 else 118 {d[nw].num-=trl[num];d[nw].simple--;} 119 } 120 void rut(ll p) 121 { 122 ll x; 123 x=rt[p]=++siz; 124 d[x].l=1;d[x].r=kiz;d[x].fl=1; 125 if(x>1) 126 { 127 d[rt[p]]=d[rt[p-1]]; 128 d[rt[p]].son[0]=d[rt[p-1]].son[0]; 129 d[rt[p]].son[1]=d[rt[p-1]].son[1]; 130 } 131 else 132 { 133 d[x].son[0]=++siz; 134 build(d[x].son[0],1,(kiz+1)>>1); 135 d[x].son[1]=++siz; 136 build(d[x].son[1],((kiz+1)>>1)+1,kiz); 137 } 138 } 139 void build(ll x,ll l,ll r) 140 { 141 d[x].l=l;d[x].r=r;d[x].fl=1; 142 if(l!=r) 143 { 144 d[x].son[0]=++siz; 145 build(siz,l,(l+r)>>1); 146 d[x].son[1]=++siz; 147 build(siz,((l+r)>>1)+1,r); 148 } 149 }
以上是关于[bzoj3932][CQOI2015]任务查询系统-题解[主席树][权值线段树]的主要内容,如果未能解决你的问题,请参考以下文章
bzoj3932 [CQOI2015]任务查询系统——主席树