bzoj2161: 布娃娃
Description
小时候的雨荨非常听话,是父母眼中的好孩子。在学校是老师的左右手,同学的好榜样。后来她成为艾利斯顿第二
代考神,这和小时候培养的良好素质是分不开的。雨荨的妈妈也为有这么一个懂事的女儿感到高兴。一次期末考试
,雨荨不知道第多少次,再次考了全年级第一名。雨荨的妈妈看到女儿100分的成绩单时,脸上又泛起了幸福的笑
容,作为奖励,她给雨荨买了n个布娃娃。细心的雨荨发现,第i个布娃娃有一个耐心值P[i]以及一个魅力值C[i],
并且还有能够忍受的耐心值的上限R[i]以及下限L[i]。当一个布娃娃j满足L[j]<=P[i]并且P[i]<=R[j],那么布娃
娃j喜欢布娃娃i。雨荨还发现,一个布娃娃有可能喜欢它自己。每个布娃娃心中都有一个谜团,具体来说就是:第
i个布娃娃想知道喜欢它的布娃娃中,魅力值第i大的布娃娃的魅力值是多少,并且称这个布娃娃的谜团答案为这个
魅力值的大小,如果不存在,那么这个布娃娃的谜团答案为0。鉴于雨荨的上司栋栋不让题目的数据过大,下面给
出数据的生成方法:给出16个参数:
Padd, Pfirst, Pmod, Pprod, Cadd, Cfirst, Cmod, Cprod, Ladd, Lfirst, Lmod, Lprod, Radd, Rfirst, Rmod, Rprod。
----------------------------------------------------------------------------------------
P[1] = Pfirst % Pmod, P[i] = (P[i-1] Pprod + Padd + i) % Pmod (i > 1)。
----------------------------------------------------------------------------------------
对于C、L、R数组也有类似的得到方式, %代表取余运算。注意:L和R数组生成完之后,如果某个布娃娃的忍耐度上
限小于下限,那么交换它的上限和下限。当然,雨荨也不会让你告诉她每个布娃娃的谜团答案,因为那样会使输出
数据很大。所以雨荨希望你告诉她,所有布娃娃谜团答案的和除以19921228的余数是多少。
Input
输入的第一行有一个整数n,代表布娃娃的个数。
输入的第二行有16个用空格隔开的整数
分别代表Padd,Pfirst,Pmod,Pprod,Cadd,Cfirst,Cmod,Cprod,Ladd,Lfirst,Lmod,Lprod,Radd,Rfirst,Rmod,Rprod。
16个参数均为1到100,000,000中的整数。
Output
输出一个整数,代表所有布娃娃谜团答案的和除以19921228的余数。
Sample Input
3
2 3 4 3 1 4 5 2 3 6 9 1 1 2 3 4
2 3 4 3 1 4 5 2 3 6 9 1 1 2 3 4
Sample Output
4
题解:
题意等价于求能覆盖某个点的所有区间中第K大的值,这个就可以用扫描线+splay去求
code:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 char ch; bool ok; 8 void read(int &x){ 9 for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1; 10 for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); 11 if (ok) x=-x; 12 } 13 const int maxn=100005; 14 const int inf=0x3f3f3f3f; 15 const int MOD=19921228; 16 int add,first,mod,prod,tmp[4][maxn]; 17 int n,idx,ans; 18 struct Data{ 19 int x,id,op; 20 }list[maxn*3]; 21 bool operator<(const Data &a,const Data &b){ 22 if (a.x!=b.x) return a.x<b.x; 23 return a.op<b.op; 24 } 25 struct Splay{ 26 #define ls son[x][0] 27 #define rs son[x][1] 28 int root,fa[maxn],son[maxn][2],siz[maxn],val[maxn]; 29 void init(){ 30 root=n+1,siz[n+1]=2,val[n+1]=inf,son[n+1][1]=n+2; 31 siz[n+2]=1,val[n+2]=-inf,fa[n+2]=n+1; 32 } 33 int which(int x){return son[fa[x]][1]==x;} 34 void updata(int x){siz[x]=siz[ls]+1+siz[rs];} 35 void rotate(int x){ 36 int y=fa[x],z=fa[y],d=which(x),dd=which(y); 37 fa[son[x][d^1]]=y,son[y][d]=son[x][d^1],fa[x]=z; 38 if (z) son[z][dd]=x; 39 son[x][d^1]=y,fa[y]=x,updata(y); 40 } 41 void splay(int x){ 42 while (fa[x]){ 43 if (!fa[fa[x]]) rotate(x); 44 else if (which(fa[x])==which(x)) rotate(fa[x]),rotate(x); 45 else rotate(x),rotate(x); 46 } 47 updata(x),root=x; 48 } 49 void insert(int x,int v){ 50 fa[x]=son[x][0]=son[x][1]=0,siz[x]=1,val[x]=v; 51 int f,t; 52 for (f=t=root;t;f=t,t=son[t][v<val[t]]); 53 fa[x]=f,son[f][v<val[f]]=x,splay(x); 54 } 55 int find_left(int x){for (;son[x][0];x=son[x][0]);return x;} 56 void _delete(int x){ 57 splay(x); 58 int y=find_left(son[x][1]); 59 fa[ls]=fa[rs]=0,splay(y),fa[ls]=y,son[y][0]=ls,updata(y); 60 } 61 int find_kth(int x,int k){ 62 if (!x) return 0; 63 if (siz[ls]>=k) return find_kth(ls,k); 64 if (siz[ls]+1==k) return x; 65 return find_kth(rs,k-siz[ls]-1); 66 } 67 int query(int k){ 68 int x=find_kth(root,k+1); 69 if (1<=x&&x<=n) return val[x]; 70 return 0; 71 } 72 }T; 73 int main(){ 74 read(n); 75 for (int op=0;op<4;op++){ 76 read(add),read(first),read(mod),read(prod); 77 tmp[op][1]=first%mod; 78 for (int i=2;i<=n;i++) tmp[op][i]=(1LL*tmp[op][i-1]*prod+add+i)%mod; 79 } 80 for (int i=1;i<=n;i++) if (tmp[2][i]>tmp[3][i]) swap(tmp[2][i],tmp[3][i]); 81 for (int i=1;i<=n;i++) list[++idx]=(Data){tmp[2][i],i,0}; 82 for (int i=1;i<=n;i++) list[++idx]=(Data){tmp[0][i],i,1}; 83 for (int i=1;i<=n;i++) list[++idx]=(Data){tmp[3][i],i,2}; 84 sort(list+1,list+idx+1),T.init(); 85 for (int i=1;i<=idx;i++){ 86 int id=list[i].id,op=list[i].op; 87 if (op==0) T.insert(id,tmp[1][id]); 88 else if (op==1) ans+=T.query(id),ans%=MOD; 89 else if (op==2) T._delete(id); 90 } 91 printf("%d\n",ans); 92 return 0; 93 }