1. 程式人生 > >【Foreign】Weed [線段樹]

【Foreign】Weed [線段樹]

選擇 sed else 討論 tor out sin mat ||

Weed

Time Limit: 20 Sec Memory Limit: 512 MB

Description

  從前有個棧,一開始是空的。
  你寫下了 m 個操作,每個操作形如 k v :
    若 k = 0,代表往棧頂加入一個數 v
    若 k = 1,則代表從棧頂彈出 v 個數,如果棧中的元素少於 v 個,則全部彈出。
  接著你又進行了 q 次修改,每次你會選擇一個操作,並且修改它的兩個參數。
  在每次修改後,你都要求出如果依次執行這些操作,最後棧中剩下的元素之和。

Input

  第一行兩個正整數 m,q,分別表示操作數和修改次數。
  接下來 m 行,每行兩個整數 k,v,代表一個操作。

  接下來 q 行,每行三個正整數 c,k,v,表示將第 c 個操作的參數修改為 k 和 v。

Output

  輸出 q 行,每行一個整數,代表依次執行所有操作後棧中剩下的元素之和。

Sample Input

  5 2
  0 3
  0 2
  0 3
  1 1
  0 5
  1 0 3
  1 0 1

Sample Output

  10
  8

HINT

  m,q ≤ 2×1e5, v ≤ 1e4

Solution

  首先,我們可以把一個操作拆成:先刪除若幹個數,然後加入若幹個數

  那麽我們可以用線段樹來維護,一個節點記錄:刪除del個數加入add個數這add個數的和是val

  那麽我們只需要支持單點修改,答案顯然就是Node[1].val。問題在於怎麽合並兩個節點的信息。

  我們分情況討論,記錄左兒子為L,右兒子為R。顯然信息形如:----+++ / -----+++討論一下 R.delL.add 的關系:

    1. 顯然當 L.add <= R.del 的時候, del 即為 L.del + R剩余的del ,add 即為 R.add,val 即為 R.val

    2. 否則,當 L.add > R.del 的時候,難點在於 L 剩下多少 val,只要討論出了這個問題,就解決了該題。

  我們令函數 Query(i, k)

表示 刪除節點 i後 k 個值,剩下的 val。那麽顯然這個也只要分類討論即可:

    1. k = R.add,返回 i.val - R.val 即可,比較顯然;

    2. k < R.add,顯然我們需要繼續往 R 遞歸,返回 i.val - R.val + Query(R, k)

    3. k > R.add,顯然我們需要往 L 遞歸,顯然 k 先減去 R.add,又因為存在R.del這一段,所以 L 的後面幾個被刪除的,要多查幾個,所以返回 Query(L, k - R.add + R.del)

  然後我們寫個線段樹,就解決了這道題啦QWQ。

Code

技術分享
  1 #include<iostream>    
  2 #include<string>    
  3 #include<algorithm>    
  4 #include<cstdio>    
  5 #include<cstring>    
  6 #include<cstdlib>
  7 #include<cmath>
  8 #include<vector>
  9 using namespace std;  
 10 typedef long long s64;
 11  
 12 const int ONE = 1e6 + 5;
 13 
 14 int m, T;
 15 
 16 struct point
 17 {
 18         int opt, val;
 19 }oper[ONE];
 20 
 21 struct power
 22 {
 23         int add, del, val;
 24 }Node[ONE * 4];
 25 
 26 int get()
 27 {    
 28         int res=1,Q=1;char c;    
 29         while( (c=getchar())<48 || c>57 ) 
 30         if(c==-)Q=-1; 
 31         res=c-48;     
 32         while( (c=getchar())>=48 && c<=57 )    
 33         res=res*10+c-48;
 34         return res*Q;
 35 }
 36 
 37 int Query(int i, int k)
 38 {
 39         int L = i << 1, R = i << 1 | 1;
 40         if(k == Node[R].add) return Node[i].val - Node[R].val;
 41         if(k < Node[R].add) return Node[i].val - Node[R].val + Query(R, k);
 42         if(k > Node[R].add) return Query(L, k - Node[R].add + Node[R].del);
 43 }
 44 
 45 power Merge(int L, int R)
 46 {
 47         power c = (power){0, 0, 0};
 48         if(Node[L].add <= Node[R].del)
 49             c.del = Node[L].del + Node[R].del - Node[L].add,
 50             c.add = Node[R].add, c.val = Node[R].val; 
 51         if(Node[L].add > Node[R].del)
 52         {
 53             c.del = Node[L].del;
 54             c.add = Node[L].add - Node[R].del + Node[R].add;
 55             c.val = Query(L, Node[R].del) + Node[R].val;
 56         }
 57         return c;
 58 }
 59 
 60 void Build(int i, int l, int r)
 61 {
 62         if(l == r)
 63         {
 64             if(oper[l].opt == 0) Node[i] = (power){1, 0, oper[l].val};
 65             else Node[i] = (power){0, oper[l].val, 0};
 66             return;
 67         }
 68         int mid = l + r >> 1;
 69         Build(i << 1, l, mid); Build(i << 1 | 1, mid + 1, r);
 70         Node[i] = Merge(i << 1, i << 1 | 1);
 71         
 72 }
 73 
 74 void Update(int i, int l, int r, int L)
 75 {
 76         if(L <= l && r <= L)
 77         {
 78             if(oper[l].opt == 0) Node[i] = (power){1, 0, oper[l].val};
 79             else Node[i] = (power){0, oper[l].val, 0};
 80             return;
 81         }
 82         int mid = l + r >> 1;
 83         if(L <= mid) Update(i << 1, l, mid, L);
 84         else Update(i << 1 | 1, mid + 1, r, L);
 85         Node[i] = Merge(i << 1, i << 1 | 1);
 86 }
 87 
 88 int main()
 89 {
 90         m = get();    T = get();
 91         for(int i = 1; i <= m; i++)
 92             oper[i].opt = get(), oper[i].val = get();
 93         Build(1, 1, m);
 94         while(T--)
 95         {
 96             int id = get();
 97             oper[id].opt = get();    oper[id].val = get();
 98             Update(1, 1, m, id);
 99             printf("%d\n", Node[1].val);
100         }
101 }
View Code

【Foreign】Weed [線段樹]