1. 程式人生 > >Luogu 3168 [CQOI2015]任務查詢系統

Luogu 3168 [CQOI2015]任務查詢系統

ecn typename 任務 觀察 時間 -- int task getchar

區間修改單點查詢,又觀察到是一個k小,考慮主席樹上做差分
一開始樣例瘋狂掛,後來發現主席樹在一個歷史版本上只能修改一次,所以要開2*n個根結點,記錄一下每個時間對應的根結點編號
然後80分,考慮到當一個排名的結點有w個而查詢的k<w時會使答案變大,所以特判(但是一開始又喜聞樂見地把符號寫反了)~
一通亂改+瘋狂提交後水過

Code:

#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;

const int
N = 1e5 + 5; const ll inf = (ll)1 << 60; int n, qn, bel[N], maxn = 0; ll val[N]; vector <int> ins[N], del[N]; struct Task { int st, ed; ll pri; } a[N]; struct Innum { int id; ll val; } in[N]; bool cmp(const Innum &x, const Innum &y) { if(x.val != y.val) return
x.val < y.val; else return x.id < y.id; } template <typename T> inline void read(T &X) { X = 0; char ch = 0; T op = 1; for(; ch > 9|| ch < 0; ch = getchar()) if(ch == -) op = -1; for(; ch >= 0 && ch <= 9; ch = getchar()) X
= (X << 3) + (X << 1) + ch - 48; X *= op; } inline int max(int x, int y) { return x > y ? x : y; } inline void discrete() { in[0].val = -inf; sort(in + 1, in + 1 + n, cmp); int cnt = 0; for(int i = 1; i <= n; i++) { if(in[i].val != in[i - 1].val) ++cnt; maxn = max(maxn, cnt); val[cnt] = in[i].val; a[in[i].id].pri = cnt; } } struct Node { int lc, rc, cntSum; ll priSum; }; namespace PSegT { int root[N << 1], nodeCnt; Node s[N * 40]; #define mid (l + r) / 2 inline void up(int p) { s[p].cntSum = s[s[p].lc].cntSum + s[s[p].rc].cntSum; s[p].priSum = s[s[p].lc].priSum + s[s[p].rc].priSum; } void insert(int &p, int l, int r, int x, int pre, int type) { p = ++nodeCnt; s[p] = s[pre]; s[p].cntSum += type; s[p].priSum += (ll)type * val[x]; if(l == r) return; if(x <= mid) insert(s[p].lc, l, mid, x, s[pre].lc, type); else insert(s[p].rc, mid + 1, r, x, s[pre].rc, type); // up(p); } ll query(int p, int l, int r, int k) { // if(l == r) return s[p].priSum; if(l == r) return k < s[p].cntSum ? (ll)k * val[l] : s[p].priSum; int now = s[s[p].lc].cntSum; ll res = 0; if(k <= now) res = query(s[p].lc, l, mid, k); else res = s[s[p].lc].priSum + query(s[p].rc, mid + 1, r, k - now); return res; } void print(int p, int l, int r) { printf("(%d %d %d %d %lld) ", p, s[p].lc, s[p].rc, s[p].cntSum, s[p].priSum); if(l == r) return; print(s[p].lc, l, mid); print(s[p].rc, mid + 1, r); } #undef mid } using namespace PSegT; int main() { read(n), read(qn); for(int i = 1; i <= n; i++) { read(a[i].st), read(a[i].ed), read(a[i].pri); in[i].val = a[i].pri, in[i].id = i; ins[a[i].st].push_back(i); del[a[i].ed + 1].push_back(i); } discrete(); nodeCnt = root[0] = 0; int rtCnt = 0; for(int i = 1; i <= qn; i++) { for(unsigned int j = 0; j < ins[i].size(); j++) ++rtCnt, insert(root[rtCnt], 1, maxn, a[ins[i][j]].pri, root[rtCnt - 1], 1); for(unsigned int j = 0; j < del[i].size(); j++) ++rtCnt, insert(root[rtCnt], 1, maxn, a[del[i][j]].pri, root[rtCnt - 1], -1); bel[i] = rtCnt; } /* for(int i = 1; i <= rtCnt; i++, printf("\n")) print(root[i], 1, maxn); */ ll ans = 1; for(int x, k, _a, _b, _c; qn--; ) { read(x), read(_a), read(_b), read(_c); k = 1 + ((ll)_a * ans + _b) % _c; if(k >= s[root[bel[x]]].cntSum) printf("%lld\n", ans = s[root[bel[x]]].priSum); else printf("%lld\n", ans = query(root[bel[x]], 1, maxn, k)); } return 0; }

感覺vector還挺快的……

Luogu 3168 [CQOI2015]任務查詢系統