Question link http://acm.sgu.ru/problem.php? Contest = 0 & problem = 263
Question: there are 10 ^ 6 locations (cells), and several cubes can be placed in each location. For any two numbers I <= j, if [I, [I, j] is a Tower, where cubes exist anywhere and the I-1 and j + 1 have no boxes. There are currently 10 ^ 6 modifications and queries to ensure legitimacy:
- Put <x> <c>-put c cubes on cell x
- Tput <t> <x> <c>-put c cubes on column x in tower with number t (towers are numbered from left to the right)
- Towers-print total number of towers built
- Cubes <t>-print the number of cubes in the tower t
- Length <t>-print the length of the tower t
- Tcubes <t> <x>-print the number of cubes in column x of the tower t
Solution: According to the question, the statistic to be maintained includes the number of cubes in a cell, the number of cubes in a tower, the length of a tower, and the number of towers, the left endpoint of tower I. Only the first option changes the tower distribution (generate new towers or merge several towers) because tower generation is passed, it is easy to think of and maintain the query set (the parent node is equivalent to the left endpoint of the Line Segment). Treap saves the left endpoint of the existing line segment, when a tower is generated, the left endpoint is inserted into the merged tower and deleted from the left endpoint to maintain the left endpoint of the tower I.
# Include <cstdio> # include <cstdlib> using namespace std; # define maxn 1000010 struct TreeNode {int key; int left, right; int size; int pri; void init () {left = right = 0; size = 1; pri = rand () ;}}; struct Treap {TreeNode nodes [maxn]; int root, cnt, count; int stack [maxn], top; void init () {count = root = cnt = top = 0; nodes [0]. pri =-0x7FFFFFFF;} int newnode () {int ret; if (top) ret = stack [-- top]; elseret = ++ cnt; no Des [ret]. init (); return ret;} void push_up (int idx) {nodes [idx]. size = nodes [nodes [idx]. left]. size + nodes [nodes [idx]. right]. size + 1;} void leftRotate (int & root) {int tmp = nodes [root]. right; nodes [root]. right = nodes [nodes [root]. right]. left; nodes [tmp]. left = root; push_up (root); push_up (tmp); root = tmp;} void rightRotate (int & root) {int tmp = nodes [root]. left; nodes [root]. left = nodes [nodes [root]. left]. r Ight; nodes [tmp]. right = root; push_up (root); push_up (tmp); root = tmp;} void insert (int k) {count ++; insert (k, root );} void insert (int k, int & root) {if (! Root) {root = newnode (); nodes [root]. key = k; return;} else if (k <nodes [root]. key) {insert (k, nodes [root]. left); if (nodes [nodes [root]. left]. pri> nodes [root]. pri) rightRotate (root);} else {insert (k, nodes [root]. right); if (nodes [nodes [root]. right]. pri> nodes [root]. pri) leftRotate (root);} push_up (root);} void del (int k) {count --; del (root, k);} void del (int & root, int k) {if (nodes [root]. key = k) {if (! Nodes [root]. left &&! Nodes [root]. right) {stack [top ++] = root; root = 0; return;} if (nodes [nodes [root]. left]. pri> nodes [nodes [root]. right]. pri) {rightRotate (root); del (nodes [root]. right, k);} else {leftRotate (root); del (nodes [root]. left, k);} push_up (root); return;} if (k <nodes [root]. key) del (nodes [root]. left, k); elsedel (nodes [root]. right, k); push_up (root);} int select (int k) {return select (root, k);} int select (int root, int K) {int s = nodes [nodes [root]. left]. size; if (s> = k) return select (nodes [root]. left, k); if (s + 1 = k) return nodes [root]. key; return select (nodes [root]. right, k-1-s) ;}} tree; int num [maxn], p [maxn]; // Number of cubes for each vertex and int count [maxn], len [maxn], left endpoint of the line segment; // Number of cubes and length of int n for the line segment whose endpoint is I, t, x, c; void init () {tree. init (); for (int I = 0; I <maxn; I ++) {len [I] = count [I] = num [I] = 0; p [I] = I;} int find (int x) {if (X = p [x]) return x; p [x] = find (p [x]); return p [x];} void put () {scanf ("% d", & x, & c); if (num [x] = 0) {count [x] = num [x] = c; len [x] = 1; tree. insert (x); if (num [x + 1]! = 0) {p [x + 1] = x; len [x] + = len [x + 1]; count [x] + = count [x + 1]; tree. del (x + 1);} if (num [x-1]! = 0) {tree. del (x); int px = find (x-1); p [x] = px; len [px] + = len [x]; count [px] + = count [x] ;}} else {int px = find (x); num [x] + = c; count [px] + = c ;}} void tput () {scanf ("% d", & t, & x, & c ); int temp = tree. select (t); num [temp + x-1] + = c; count [temp] + = c;} void towers () {int temp = tree. count; printf ("% d towers \ n", temp);} void cubes () {scanf ("% d", & t); int temp = tree. select (t); printf ("% d cubes in % dth tower \ n", count [temp], t);} void length () {scanf ("% d ", & t); int temp = tree. select (t); printf ("length of % dth tower is % d \ n", t, len [temp]);} void tcubes () {scanf ("% d", & t, & x); int temp = tree. select (t); printf ("% d cubes in % dth column of % dth tower \ n", num [temp + x-1], x, t);} int main () {char ch [10]; scanf ("% d", & n); init (); while (n --) {scanf ("% s", ch ); if (ch [0] = 'P') put (); if (ch [0] = 'T' & ch [1] = 'P ') tput (); if (ch [0] = 'T' & ch [1] = 'O') towers (); if (ch [0] = 'C') cubes (); if (ch [0] = 'l') length (); if (ch [0] = 'T' & ch [1] = 'C') tcubes () ;} return 0 ;}