zoukankan      html  css  js  c++  java
  • Transformation 线段树好题 好题 (独立写出来对线段树不容易)

    Transformation

    Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 65535/65536 K (Java/Others)
    Total Submission(s): 7144    Accepted Submission(s): 1811


    Problem Description
    Yuanfang is puzzled with the question below:
    There are n integers, a1, a2, …, an. The initial values of them are 0. There are four kinds of operations.
    Operation 1: Add c to each number between ax and ay inclusive. In other words, do transformation ak<---ak+c, k = x,x+1,…,y.
    Operation 2: Multiply c to each number between ax and ay inclusive. In other words, do transformation ak<---ak×c, k = x,x+1,…,y.
    Operation 3: Change the numbers between ax and ay to c, inclusive. In other words, do transformation ak<---c, k = x,x+1,…,y.
    Operation 4: Get the sum of p power among the numbers between ax and ay inclusive. In other words, get the result of axp+ax+1p+…+ay p.
    Yuanfang has no idea of how to do it. So he wants to ask you to help him.
     
    Input
    There are no more than 10 test cases.
    For each case, the first line contains two numbers n and m, meaning that there are n integers and m operations. 1 <= n, m <= 100,000.
    Each the following m lines contains an operation. Operation 1 to 3 is in this format: "1 x y c" or "2 x y c" or "3 x y c". Operation 4 is in this format: "4 x y p". (1 <= x <= y <= n, 1 <= c <= 10,000, 1 <= p <= 3)
    The input ends with 0 0.
     
    Output
    For each operation 4, output a single integer in one line representing the result. The answer may be quite large. You just need to calculate the remainder of the answer when divided by 10007.
     
    Sample Input
    5 5 3 3 5 7 1 2 4 4 4 1 5 2 2 2 5 8 4 3 5 3 0 0
     
    Sample Output
    307 7489
     
    这题是好题  
    太太太恶心了
    简直爆炸  ,这题我写了N次
    取模取模  
    最后的query也要取模
    找BUG找了好久找不到
    这题最傻逼的做法是用3个lazy 和 3 个sum 
    但是这里对于不同的lazy优先级不同 
    而且还有取模操作,那样写下来及其的繁琐
    我参考大佬博客 发现这题最优化的写法应该是
    开一个线段树 维护区间里面相同的值
    这样的话无论C多少都好求
            for (int i = 1 ; i <= c ; i++)
                   ans = (ans * tree[rt].eq) % mod;
            return (ans * ((tree[rt].r - tree[rt].l + 1) % mod) % mod) % mod;
    如果C是10用多个lazy维护代码量就直接爆炸了
    这样的方法还有一个很好的优化
    就是pushdown操作一直递归下去,直到到达底层
    这样的话就有效的解决繁琐的优先级处理问题
    这样处理优先级问题就很容易了
    我菜爆了,用线段树维护区间相同的值 ,太强了
     
    附送一个fuck函数
     
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <queue>
      6 #include <stack>
      7 using namespace std;
      8 typedef long long LL;
      9 #define fuck(x) cout<<"["<<x<<"]";
     10 #define  rtl rt<<1
     11 #define  rtr rt<<1|1
     12 const int maxn = 1e5 + 10;
     13 const int mod = 1e4 + 7;
     14 const int INF = 2e9 + 7;
     15 int n, m;
     16 struct node {
     17     int l, r, eq, add, mul;
     18     int mid() {
     19         return (l + r) >> 1;
     20     }
     21 } tree[maxn << 2];
     22 void build(int l, int r, int rt) {
     23     tree[rt].l = l, tree[rt].r = r;
     24     tree[rt].add = 0, tree[rt].mul = 1, tree[rt].eq = -1;
     25     if (l == r) {
     26         tree[rt].eq = 0;
     27         return ;
     28     }
     29     int m = (l + r) >> 1;
     30     build(l, m, rtl);
     31     build(m + 1, r, rtr);
     32 }
     33 void pushdown(int rt) {
     34     if (tree[rt].l == tree[rt].r) return ;
     35     if (tree[rt].eq != -1) {
     36         tree[rtl].eq = tree[rtr].eq = tree[rt].eq;
     37         tree[rtl].add = tree[rtr].add = 0;
     38         tree[rtl].mul = tree[rtr].mul = 1;
     39         tree[rt].eq = -1;
     40         return ;
     41     }
     42     if (tree[rt].mul != 1) {
     43         if (tree[rtl].eq != -1) tree[rtl].eq = (tree[rtl].eq * tree[rt].mul) % mod;
     44         else {
     45             pushdown(rtl);
     46             tree[rtl].mul = (tree[rtl].mul * tree[rt].mul) % mod;
     47         }
     48         if (tree[rtr].eq != -1) tree[rtr].eq = (tree[rtr].eq * tree[rt].mul) % mod;
     49         else {
     50             pushdown(rtr);
     51             tree[rtr].mul = (tree[rtr].mul * tree[rt].mul) % mod;
     52         }
     53         tree[rt].mul = 1;
     54     }
     55     if (tree[rt].add) {
     56         if (tree[rtl].eq != -1) tree[rtl].eq = (tree[rtl].eq + tree[rt].add) % mod;
     57         else {
     58             pushdown(rtl);
     59             tree[rtl].add = (tree[rtl].add + tree[rt].add) % mod;
     60         }
     61         if (tree[rtr].eq != -1) tree[rtr].eq = (tree[rtr].eq + tree[rt].add) % mod;
     62         else {
     63             pushdown(rtr);
     64             tree[rtr].add = (tree[rtr].add + tree[rt].add) % mod;
     65         }
     66         tree[rt].add = 0;
     67     }
     68 }
     69 
     70 void update(int L, int R, int rt, int op, int c) {
     71     if (L <= tree[rt].l && tree[rt].r <= R ) {
     72         if (op == 3) {
     73             tree[rt].eq = c;
     74             tree[rt].mul = 1;
     75             tree[rt].add = 0;
     76             return ;
     77         }
     78         if (tree[rt].eq != -1) {
     79             if (op == 1) tree[rt].eq = (tree[rt].eq + c) % mod;
     80             else tree[rt].eq = (tree[rt].eq * c) % mod;
     81         } else {
     82             pushdown(rt);
     83             if (op == 1) tree[rt].add = (tree[rt].add + c) % mod;
     84             else tree[rt].mul = (tree[rt].mul * c) % mod;
     85         }
     86         return ;
     87     }
     88     pushdown(rt);
     89     int m = tree[rt].mid();
     90     if (L <= m) update(L, R, rtl, op, c);
     91     if (R > m)  update(L, R, rtr, op, c);
     92 }
     93 
     94 int query(int L, int R, int rt, int c) {
     95     if (L <= tree[rt].l && tree[rt].r <= R && tree[rt].eq != -1) {
     96         int ans = 1;
     97         for (int i = 1 ; i <= c ; i++)
     98             ans = (ans * tree[rt].eq) % mod;
     99         return (ans * ((tree[rt].r - tree[rt].l + 1) % mod) % mod) % mod;
    100     }
    101     pushdown(rt);
    102     int m = tree[rt].mid();
    103     if (R <= m) return  query(L, R, rtl, c);
    104     else if (L > m) return  query(L, R, rtr, c);
    105     else  return  query(L, m, rtl, c) + query(m + 1, R, rtr, c);
    106 }
    107 int main() {
    108     while(scanf("%d%d", &n, &m) != EOF) {
    109         if (n == 0 && m == 0) break;
    110         build(1, n, 1);
    111         while(m--) {
    112             int op, x, y, c;
    113             scanf("%d%d%d%d", &op, &x, &y, &c);
    114             if (op == 4) printf("%d
    ", query(x, y, 1, c)%mod);
    115             else update(x, y, 1, op, c);
    116         }
    117     }
    118     return 0;
    119 }
     
  • 相关阅读:
    如何使用谷歌的网页删除请求工具?
    已有记录表添加特定排序主键ID
    用ASP实现超长内容的word模板替换objDoc.Content.Find.Execute
    内网SMTP发送失败的曲线救国之策
    IIS无法在后台生成WORD文件的故障
    WINDOWS2003进行WindowsFTP设置的一些注意事项
    解决IISASP调用XmlHTTP出现msxml3.dll (0x80070005) 拒绝访问的错误
    [转]Cate:我是如何准备Google面试的
    Ubuntu的启动配置文件grub.cfg(menu.lst)设置指南
    Linux启动过程详解
  • 原文地址:https://www.cnblogs.com/qldabiaoge/p/9380209.html
Copyright © 2011-2022 走看看