• 【Foreign】Weed [线段树]


    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
    ", Node[1].val);
    100         }
    101 }
    View Code
  • 相关阅读:
    豆瓣电台WP7客户端 MVVM重构记录之使用MVVM Light实现Event绑定
    使用DotNetOpenAuth来实现有道云笔记的授权
    豆瓣电台WP7客户端 MVVM重构记录之总结
    使用Npgsql连接Postgres
    WPF自定义一个MessageBox
    字符集其实很简单
    pytest封神之路第六步 断言技巧
    pytest封神之路第七步 用例查找原理
    一文搞懂Cookie,Session,Token,JWT
    典藏版Web功能测试用例库
  • 原文地址:https://www.cnblogs.com/BearChild/p/7616774.html
Copyright © 2020-2023  润新知