仿佛没用过std::set
Seniorious has n pieces of talisman. Willem puts them in a line, the i-th of which is an integer ai.
In order to maintain it, Willem needs to perform m operations.
There are four types of operations:
- 1 l r x: For each i such that l ≤ i ≤ r, assign ai + x to ai.
- 2 l r x: For each i such that l ≤ i ≤ r, assign x to ai.
- 3 l r x: Print the x-th smallest number in the index range [l, r], i.e. the element at the x-th position if all the elements ai such that l ≤ i ≤ r are taken and sorted into an array of non-decreasing integers. It's guaranteed that 1 ≤ x ≤ r - l + 1.
- 4 l r x y: Print the sum of the x-th power of ai such that l ≤ i ≤ r, modulo y, i.e. .
Input
The only line contains four integers n, m, seed, vmax (1 ≤ n, m ≤ 105, 0 ≤ seed < 109 + 7, 1 ≤ vmax ≤ 109).
The initial values and operations are generated using following pseudo code:
def rnd():
ret = seed
seed = (seed * 7 + 13) mod 1000000007
return ret
for i = 1 to n:
a[i] = (rnd() mod vmax) + 1
for i = 1 to m:
op = (rnd() mod 4) + 1
l = (rnd() mod n) + 1
r = (rnd() mod n) + 1
if (l > r):
swap(l, r)
if (op == 3):
x = (rnd() mod (r - l + 1)) + 1
else:
x = (rnd() mod vmax) + 1
if (op == 4):
y = (rnd() mod vmax) + 1
Here op is the type of the operation mentioned in the legend.
Output
For each operation of types 3 or 4, output a line containing the answer.
题目分析
ODT的入门例题。
ODT实际上是将区间缩成点,用平衡树来维护区间的过程。这个东西的“复杂度”只能够依赖于数据随机。
具体可以参考:【毒瘤Warning】Chtholly Tree珂朵莉树详解
1 #include<bits/stdc++.h> 2 typedef long long ll; 3 const int maxn = 100035; 4 5 struct node 6 { 7 int l,r; 8 mutable ll val; 9 node(int a=0, int b=0, ll c=0):l(a),r(b),val(c) {} 10 bool operator < (node a) const 11 { 12 return l < a.l; 13 } 14 }; 15 typedef std::set<node>::iterator itr; 16 int n,m,p,seed,vmax,a[maxn]; 17 std::set<node> s; 18 19 int rand() 20 { 21 int ret = seed; 22 seed = (seed*7ll+13)%1000000007; 23 return ret; 24 } 25 ll qmi(ll a, ll b) 26 { 27 ll ret = 1; 28 for (a%=p; b; b>>=1,a=1ll*a*a%p) 29 if (b&1) ret = 1ll*ret*a%p; 30 return ret; 31 } 32 itr split(int pos) 33 { 34 itr loc = s.lower_bound(node(pos)); 35 if (loc!=s.end()&&(*loc).l==pos) return loc; 36 --loc; 37 int l = (*loc).l, r = (*loc).r; 38 ll val = (*loc).val; 39 s.erase(loc); 40 s.insert(node(l, pos-1, val)); 41 return s.insert(node(pos, r, val)).first; 42 } 43 void merge(int l, int r, int val) 44 { 45 itr rpos = split(r+1), lpos = split(l); 46 s.erase(lpos, rpos); 47 s.insert(node(l, r, val)); 48 } 49 void modify(int l, int r, int val) 50 { 51 itr rpos = split(r+1), lpos = split(l); 52 for (; lpos!=rpos; ++lpos) (*lpos).val += val; 53 } 54 ll getRank(int l, int r, int k) 55 { 56 itr rpos = split(r+1), lpos = split(l); 57 std::vector<std::pair<ll, int> > mp; 58 for (; lpos!=rpos; ++lpos) 59 mp.push_back(std::make_pair((*lpos).val, (*lpos).r-(*lpos).l+1)); 60 std::sort(mp.begin(), mp.end()); 61 for (int i=0,mx=mp.size(); i<mx; i++) 62 { 63 k -= mp[i].second; 64 if (k <= 0) return mp[i].first; 65 } 66 return -1; 67 } 68 int calc(int l, int r, int x) 69 { 70 int ret = 0; 71 itr rpos = split(r+1), lpos = split(l); 72 for (; lpos!=rpos; ++lpos) 73 ret = (ret+1ll*qmi((*lpos).val, x)*((*lpos).r-(*lpos).l+1)%p)%p; 74 return ret; 75 } 76 int main() 77 { 78 scanf("%d%d%d%d",&n,&m,&seed,&vmax); 79 for (int i=1; i<=n; i++) 80 { 81 a[i] = rand()%vmax+1; 82 s.insert(node(i, i, a[i])); 83 } 84 s.insert(node(n+1, n+1, 0)); 85 for (int i=1,x; i<=m; i++) 86 { 87 int opt = rand()%4+1, l = rand()%n+1, r = rand()%n+1; 88 if (l > r) std::swap(l, r); 89 if (opt==3) x = rand()%(r-l+1)+1; 90 else x = (rand()%vmax)+1; 91 if (opt==1) modify(l, r, x); 92 else if (opt==2) merge(l, r, x); 93 else if (opt==3) printf("%lld ",getRank(l, r, x)); 94 else{ 95 p = rand()%vmax+1; 96 printf("%d ",calc(l, r, x)); 97 } 98 } 99 return 0; 100 }
END