CF896C Willem, Chtholly and Seniorious
阿新 • • 發佈:2018-10-25
第一篇 sta long sync hot mat += first bool
話說,研究珂學的最好方式是……
其實珂朵莉樹很久之前就看過UESTC的那個介紹了,但是由於太菜,聽都聽不懂。
現在過來學一學,才發現太暴力太優美了!我愛珂朵莉。。。
這道題要你弄的4個操作是區間加、區間推平、區間排序後的第\(k\)大值和區間任意冪次和。
比較有難度的就是區間任意冪次和。暴力顯然行不通的啊!!!
講道理,珂朵莉樹是我看過的唯一支持維護區間任意冪次和的數據結構。
所以用珂朵莉樹來搞一搞?
珂朵莉樹的單個節點是這樣的:
struct Nodes { ll l, r; mutable ll val; Nodes(ll l, ll r = -1, ll val = 0): l(l), r(r), val(val){} bool operator < (const Nodes &rhs) const { return l < rhs.l; } }; std::set<Nodes> chotholly;
其中3個變量代表了\([l,r]\)這段區間中的所有數字都是\(val\)!一個節點代表了多個點。
然後用一個set::set來維護這顆珂朵莉樹。
顯然,如果區間推平操作比較多,節點的個數會比較小。
所以,珂朵莉樹的靈魂就是:區間推平的操作不會太少(數據隨機是其中一例)。
所以,你做的要死的毒瘤數據結構題,也許還能用珂朵莉樹輕松地做過去!
具體看代碼吧。luogu的第一篇題解講得太好了,直接去那裏學習就可以了。
對了!這道題卡快速冪!!!x的初值也要取膜!
代碼:
#include<iostream> #include<set> #include<vector> #include<algorithm> typedef long long ll; const int maxn = 100005; ll n, m, seed, vmax; struct Nodes { ll l, r; mutable ll val; Nodes(ll l, ll r = -1, ll val = 0): l(l), r(r), val(val){} bool operator < (const Nodes &rhs) const { return l < rhs.l; } }; std::set<Nodes> chotholly; struct Temp { ll len, val; Temp(ll len, ll val): len(len), val(val){} bool operator < (const Temp &rhs) const { return val < rhs.val; } }; #define IT std::set<Nodes>::iterator void print(IT it) { std::cout << it->l << ‘ ‘ << it->r << ‘ ‘ << it->val << std::endl; } IT split(ll pos)// get iterator starting from a[pos] { IT it = chotholly.lower_bound(Nodes(pos)); if(it != chotholly.end() && it->l == pos) return it; --it; ll l = it->l, r = it->r, val = it->val; chotholly.erase(it); chotholly.insert(Nodes(l, pos - 1, val)); return chotholly.insert(Nodes(pos, r, val)).first; } void assign(ll l, ll r, ll x) { IT itl = split(l), itr = split(r + 1); //print(itl); //print(itr); chotholly.erase(itl, itr); chotholly.insert(Nodes(l, r, x)); } void interval_add(ll l, ll r, ll x) { IT itl = split(l), itr = split(r + 1); for(; itl != itr; ++itl) itl->val += x; } ll kth(ll l, ll r, ll k) { std::vector<Temp> vec; IT itl = split(l), itr = split(r + 1); for(; itl != itr; ++itl) vec.push_back(Temp(itl->r - itl->l + 1, itl->val)); std::sort(vec.begin(), vec.end()); for(std::vector<Temp>::iterator it = vec.begin(); it != vec.end(); ++it) { k -= it->len; if(k <= 0) return it->val; } return -1ll; } ll pow_mod(ll x, ll y, ll z) { ll ans = 1; x %= z;// 不取膜你會死在第3個測試點 while(y) { if(y & 1) ans = ans * x % z; x = x * x % z; y >>= 1; } return ans % z; } ll ssum(ll l, ll r, ll x, ll y) { ll ans = 0; IT itl = split(l), itr = split(r + 1); for(; itl != itr; ++itl) { ans = (ans + (itl->r - itl->l + 1) * pow_mod(itl->val, x, y)) % y; } return ans % y; } ll rnd() { ll ret = seed; seed = (seed * 7 + 13) % 1000000007; return ret; } int main() { std::ios::sync_with_stdio(false); std::cin >> n >> m >> seed >> vmax; for(int i = 1; i <= n; i++) { ll a_i = (rnd() % vmax) + 1; chotholly.insert(Nodes(i, i, a_i)); } chotholly.insert(Nodes(n + 1, n + 1, 0));// 不知道為什麽 for(int i = 1; i <= m; i++) { ll opt, l, r, x, y; opt = (rnd() % 4) + 1; l = (rnd() % n) + 1; r = (rnd() % n) + 1; if(l > r) std::swap(l, r); if(opt == 3) x = (rnd() % (r - l + 1)) + 1; else x = (rnd() % vmax) + 1; if(opt == 4) y = (rnd() % vmax) + 1; if(opt == 1) interval_add(l, r, x); else if(opt == 2) assign(l, r, x); else if(opt == 3) std::cout << kth(l, r, x) << std::endl; else if(opt == 4) std::cout << ssum(l, r, x, y) << std::endl; } return 0; }
CF896C Willem, Chtholly and Seniorious