看Tutorial理解了信息维护的办法,CF很人性化啊,以后转战CF。
这题线段树和splay都可以搞。
线段树:
需要离散化,一开始Move the pj-th理解成了当前序列第pj小的元素,心说这咋离散化啊,
尼玛还要再建个平衡树维护离散化过程,也太恶心吧,又看了下要求是初始的第pj个元素,
这就好办了,不过线段树搞这种题赶脚好麻烦,以后遇到需要移动元素的还是果断splay吧
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <queue> #include <algorithm> #include <vector> #include <cstring> #include <stack> #include <cctype> #include <utility> #include <map> #include <string> #include <climits> #include <set> #include <string> #include <sstream> #include <utility> #include <ctime> using std::priority_queue; using std::vector; using std::swap; using std::stack; using std::sort; using std::max; using std::min; using std::pair; using std::map; using std::string; using std::cin; using std::cout; using std::set; using std::queue; using std::string; using std::istringstream; using std::make_pair; using std::getline; using std::greater; using std::endl; using std::multimap; using std::deque; typedef long long LL; typedef unsigned long long ULL; typedef pair<int, int> PAIR; typedef multimap<int, int> MMAP; const int MAXN(200010); const int MAXM(10010); const int MAXE(10010); const int MAXH(19); const int INFI(2000000000); const int MOD(10000); const ULL BASE(31); const LL LIM(10000000); const int INV(-10000); struct ELE { int num; bool flag; friend bool operator < (const ELE &op1, const ELE &op2) { return op1.num == op2.num? op1.flag: op1.num < op2.num; } }; ELE table[MAXN]; int quant; int arr[100010], tarr[100010]; struct SEGMENT_TREE { struct NODE { LL sum, ans; int size; }; NODE node[MAXN << 2]; inline int lson(int sour){return sour << 1;} inline int rson(int sour){return (sour << 1)|1;} void push_up(NODE &sour, NODE &ls, NODE &rs) { sour.size = ls.size+rs.size; sour.sum = ls.sum+rs.sum; sour.ans = ls.size*rs.sum-ls.sum*rs.size+ls.ans+rs.ans; } void build(int l, int r, int rt) { if(l == r) { node[rt].ans = 0; node[rt].size = table[l].flag? 1: 0; node[rt].sum = table[l].flag? table[l].num: 0; return; } int m = (l+r) >> 1; build(l, m, lson(rt)); build(m+1, r, rson(rt)); push_up(node[rt], node[lson(rt)], node[rson(rt)]); } int goal, flag, value; void change(int l, int r, int rt) { if(l == r) { node[rt].size = flag? 1: 0; node[rt].sum = flag? value: 0; return; } int m = (l+r) >> 1; if(goal <= m) change(l, m, lson(rt)); else change(m+1, r, rson(rt)); push_up(node[rt], node[lson(rt)], node[rson(rt)]); } int select(int l, int r, int rt, int kth) { if(l == r) return l; int m = (l+r) >> 1; if(kth <= node[lson(rt)].size) return select(l, m, lson(rt), kth); else return select(m+1, r, rson(rt), kth-node[lson(rt)].size); } int ql, qr; void query(int l, int r, int rt, NODE &ret) { if(ql <= l && qr >= r) { ret = node[rt]; return ; } int m = (l+r) >> 1; NODE t1, t2; if(ql <= m) query(l, m, lson(rt), t1); else t1.ans = t1.sum = t1.size = 0; if(qr > m) query(m+1, r, rson(rt), t2); else t2.ans = t2.sum = t2.size = 0; push_up(ret, t1, t2); } }; SEGMENT_TREE st; int find(int goal) { int l = 1, r = quant+1; while(l < r) { int m = (l+r) >> 1; if(table[m].num < goal) l = m+1; else r = m; } return l; } int op[100010][3]; int main() { int n; while(~scanf("%d", &n)) { quant = 0; table[++quant].num = -INFI; table[quant].flag = true; table[++quant].num = INFI; table[quant].flag = true; for(int i = 1; i <= n; ++i) { scanf("%d", arr+i); table[++quant].num = tarr[i] = arr[i]; table[quant].flag = true; } int m; scanf("%d", &m); for(int i = 1; i <= m; ++i) { scanf("%d%d%d", op[i], op[i]+1, op[i]+2); if(op[i][0] == 1) { arr[op[i][1]] += op[i][2]; table[++quant].num = arr[op[i][1]]; table[quant].flag = false; } } sort(table+1, table+1+quant); int temp = quant; quant = 1; for(int i = 2; i <= temp; ++i) if(table[i].num != table[quant].num) table[++quant] = table[i]; st.build(1, quant, 1); for(int i = 1; i <= m; ++i) { if(op[i][0] == 1) { int ind = find(tarr[op[i][1]]); st.goal = ind; st.flag = 0; st.change(1, quant, 1); tarr[op[i][1]] += op[i][2]; ind = find(tarr[op[i][1]]); st.goal = ind; st.flag = 1; st.value = tarr[op[i][1]]; st.change(1, quant, 1); } else { int ind = find(op[i][1]); st.ql = ind; ind = find(op[i][2]); if(table[ind].num > op[i][2]) --ind; st.qr = ind; SEGMENT_TREE::NODE ans; st.query(1, quant, 1, ans); printf("%I64d\n", ans.ans); } } } return 0; }
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <queue> #include <algorithm> #include <vector> #include <cstring> #include <stack> #include <cctype> #include <utility> #include <map> #include <string> #include <climits> #include <set> #include <string> #include <sstream> #include <utility> #include <ctime> using std::priority_queue; using std::vector; using std::swap; using std::stack; using std::sort; using std::max; using std::min; using std::pair; using std::map; using std::string; using std::cin; using std::cout; using std::set; using std::queue; using std::string; using std::istringstream; using std::make_pair; using std::getline; using std::greater; using std::endl; using std::multimap; using std::deque; typedef long long LL; typedef unsigned long long ULL; typedef pair<int, int> PAIR; typedef multimap<int, int> MMAP; const int MAXN(100015); const int MAXM(10010); const int MAXE(10010); const int MAXH(19); const int INFI(2000000000); const int MOD(10000); const ULL BASE(31); const LL LIM(10000000); const int INV(-10000); int arr[MAXN]; int tarr[MAXN]; struct SPLAY_TREE { struct NODE { int num, size; LL sum, ans; NODE *fa; NODE *ch[2]; }; NODE pool[MAXN]; NODE *root, *NIL, *rear; inline void push_up(NODE *sour) //一定要注意NIL节点对push_up的影响 { NODE *ls = sour->ch[0], *rs = sour->ch[1]; LL temp; temp = (LL)sour->num*ls->size-ls->sum+ls->ans; //小心这里暴int sour->ans = (ls->size+1)*rs->sum-(ls->sum+sour->num)*rs->size+temp+rs->ans; sour->size = ls->size+rs->size+1; sour->sum = ls->sum+rs->sum+sour->num; } void initNIL() { NIL->ch[0] = NIL->ch[1] = NIL->fa = NIL; NIL->sum = NIL->ans = 0; NIL->size = 0; } void init(int n) { NIL = pool; initNIL(); rear = pool+1; newnode(root, NIL, -INFI); //插入无穷小 newnode(root->ch[1], root, INFI); //插入无穷大 build_tree(root->ch[1]->ch[0], root->ch[1], 1, n); //建树 push_up(root->ch[1]); push_up(root); } void newnode(NODE *&sour, NODE *f, int num) { sour = rear++; sour->sum = sour->num = num; sour->ans = 0; sour->size = 1; sour->fa = f; sour->ch[0] = sour->ch[1] = NIL; } void build_tree(NODE *&sour, NODE *f, int l, int r) { if(l > r) return; int m = (l+r) >> 1; newnode(sour, f, arr[m]); build_tree(sour->ch[0], sour, l, m-1); build_tree(sour->ch[1], sour, m+1, r); push_up(sour); } void rotate(NODE *sour, int flag) { NODE *f = sour->fa; // push_down(f); // push_down(sour); f->ch[!flag] = sour->ch[flag]; sour->ch[flag]->fa = f; sour->fa = f->fa; if(f->fa != NIL) f->fa->ch[f->fa->ch[1] == f] = sour; sour->ch[flag] = f; f->fa = sour; push_up(f); } void splay(NODE *sour, NODE *goal) { // push_down(sour); while(sour->fa != goal) { if(sour->fa->fa == goal) rotate(sour, sour->fa->ch[0] == sour); else { NODE *f = sour->fa; int flag = (f->fa->ch[0] == f); if(f->ch[flag] == sour) rotate(sour, !flag); else rotate(f, flag); rotate(sour, flag); } } push_up(sour); if(goal == NIL) root = sour; } NODE *select(NODE *sour, int r) { while(sour != NIL) { // push_down(sour); if(r == sour->ch[0]->size+1) break; if(r <= sour->ch[0]->size) sour = sour->ch[0]; else { r -= sour->ch[0]->size+1; sour = sour->ch[1]; } } return sour; } inline void pick(int pos1, int pos2) { NODE *tp = select(root, pos1); splay(tp, NIL); tp = select(root, pos2+2); splay(tp, root); } int goal; NODE *pre(NODE *sour) { if(sour == NIL) return NIL; if(goal <= sour->num) return pre(sour->ch[0]); else { NODE *temp = pre(sour->ch[1]); return temp == NIL? sour: temp; } } NODE *suc(NODE *sour) { if(sour == NIL) return NIL; if(goal < sour->num) { NODE *temp = suc(sour->ch[0]); return temp == NIL? sour: temp; } else return suc(sour->ch[1]); } void MOVE(int cod, int d) { NODE *tp1, *tp2; goal = cod; tp1 = pre(root); splay(tp1, NIL); tp1 = suc(root); splay(tp1, root); tp2 = tp1->ch[0]; tp1->ch[0] = NIL; push_up(root->ch[1]); push_up(root); tp2->num = tp2->sum = goal = cod+d; tp2->ans = 0; tp1 = pre(root); splay(tp1, NIL); tp1 = suc(root); splay(tp1, root); tp1->ch[0] = tp2; tp2->fa = tp1; push_up(root->ch[1]); push_up(root); } LL QUERY(int l, int r) { goal = l; NODE *tp1 = pre(root); splay(tp1, NIL); goal = r; tp1 = suc(root); splay(tp1, root); return tp1->ch[0]->ans; } }; SPLAY_TREE spt; int main() { int n; while(~scanf("%d", &n)) { for(int i = 1; i <= n; ++i) scanf("%d", arr+i), tarr[i] = arr[i]; sort(arr+1, arr+1+n); spt.init(n); int m; scanf("%d", &m); int op1, op2, op3; for(int i = 0; i < m; ++i) { scanf("%d%d%d", &op1, &op2, &op3); if(op1 == 1) { spt.MOVE(tarr[op2], op3); tarr[op2] += op3; } else { LL temp = spt.QUERY(op2, op3); printf("%I64d\n", temp); } } } return 0; }