标签:好孩子 sof define 关键字 class highlight bzoj 线段树 复杂
题目描述
输入
输出
输出一个整数,代表所有布娃娃谜团答案的和除以19921228的余数。
样例输入
3
2 3 4 3 1 4 5 2 3 6 9 1 1 2 3 4
样例输出
4
题目大意
给你若干个区间,每个区间有一个权值。现在对于若干个点,求所有包含该点的区间中权值第k大的是多少。
题解
权值线段树
由于询问不是强制在线的,因此可以把所有位置排序,然后扫一遍。
对于每段区间,把它看成两个点:$l$位置加入,$r$位置删除。把每个区间的两个点和询问点以坐标为关键字放到一起排序,坐标相同的按照加入、询问、删除的顺序排序,然后从左向右扫一遍,扫到加入就把权值加入到权值线段树中;扫到询问就在权值线段树中查询第k大;扫到删除就在权值线段树中删除。
时间复杂度$O(n\log n)$。
#include <cstdio> #include <cstring> #include <algorithm> #define N 100010 #define lson l , mid , x << 1 #define rson mid + 1 , r , x << 1 | 1 using namespace std; typedef long long ll; struct data { int p , org , id; data(int p0 = 0 , int org0 = 0 , int id0 = 0) {p = p0 , org = org0 , id = id0;} bool operator<(const data &a)const {return p == a.p ? org > a.org : p < a.p;} }a[N * 3]; int P[N] , C[N] , L[N] , R[N] , v[N] , si[N << 2]; void update(int p , int a , int l , int r , int x) { si[x] += a; if(l == r) return; int mid = (l + r) >> 1; if(p <= mid) update(p , a , lson); else update(p , a , rson); } int query(int k , int l , int r , int x) { if(l == r) return l; int mid = (l + r) >> 1; if(k <= si[x << 1 | 1]) return query(k , rson); else return query(k - si[x << 1 | 1] , lson); } int main() { int n , Padd , Pfirst , Pmod , Pprod , Cadd , Cfirst , Cmod , Cprod , Ladd , Lfirst , Lmod , Lprod , Radd , Rfirst , Rmod , Rprod , i , ans = 0; scanf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d" , &n , &Padd , &Pfirst , &Pmod , &Pprod , &Cadd , &Cfirst , &Cmod , &Cprod , &Ladd , &Lfirst , &Lmod , &Lprod , &Radd , &Rfirst , &Rmod , &Rprod); P[1] = Pfirst % Pmod; for(i = 2 ; i <= n ; i ++ ) P[i] = ((ll)P[i - 1] * Pprod + Padd + i) % Pmod; C[1] = Cfirst % Cmod; for(i = 2 ; i <= n ; i ++ ) C[i] = ((ll)C[i - 1] * Cprod + Cadd + i) % Cmod; L[1] = Lfirst % Lmod; for(i = 2 ; i <= n ; i ++ ) L[i] = ((ll)L[i - 1] * Lprod + Ladd + i) % Lmod; R[1] = Rfirst % Rmod; for(i = 2 ; i <= n ; i ++ ) R[i] = ((ll)R[i - 1] * Rprod + Radd + i) % Rmod; for(i = 1 ; i <= n ; i ++ ) { if(L[i] > R[i]) swap(L[i] , R[i]); a[i * 3 - 2] = data(L[i] , 1 , i); a[i * 3 - 1] = data(R[i] , -1 , i); a[i * 3] = data(P[i] , 0 , i); v[i] = C[i]; } sort(v + 1 , v + n + 1); for(i = 1 ; i <= n ; i ++ ) C[i] = lower_bound(v + 1 , v + n + 1 , C[i]) - v; sort(a + 1 , a + 3 * n + 1); for(i = 1 ; i <= 3 * n ; i ++ ) { if(a[i].org) update(C[a[i].id] , a[i].org , 1 , n , 1); else if(si[1] >= a[i].id) ans = (ans + v[query(a[i].id , 1 , n , 1)]) % 19921228; } printf("%d\n" , ans); return 0; }
标签:好孩子 sof define 关键字 class highlight bzoj 线段树 复杂
原文地址:http://www.cnblogs.com/GXZlegend/p/7481859.html