hdu4578Transformation(线段树+懒标记优化+思维)

题目描述:

Transformation

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.
 
思路:前三种操作都好说,主要是第四个次方的操作,这个没有特别的方法,只有暴力求,但是呢
这道题的第三个操作是把区间内的值设置为一样的,那如果操作四的时候查询的区间的值都是
一样的,那不就能只需要求一个数的次方,然后乘上区间长度(r-l+1),就能快速求得值,这就是优化的
方法,还是比较考思维的.而且细节还很多,本蒟蒻没做出来,找学长要的题解.....
AC代码
#pragma once
#include<iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include<vector>
#include<map>
#include<cmath>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int maxn = 1e5 + 10;
const int M = 10007;
int lazy[maxn << 2][3];//0,1,2对应+ * =
int N;
void build(int l, int r, int rt) {
    lazy[rt][0] = 0;//初始化标记
    lazy[rt][1] = 1;
    lazy[rt][2] = -1;
    if (l == r) {
        lazy[rt][2] = 0;
        return;
    }
    if (l != r) {
        int mid = (l + r) >> 1;
        build(lson);
        build(rson);
    }
}
void pushdown(int l, int r, int rt) {//向下更新任务
    if (l == r)return;
    int mid = (l + r) >> 1;
    int ls = rt << 1, rs = rt << 1 | 1;
    if (lazy[rt][2] != -1) {
        lazy[ls][2] = lazy[rs][2] = lazy[rt][2];//子区间继承标记
        lazy[ls][0] = lazy[rs][0] = 0;//清空子区间+标记
        lazy[ls][1] = lazy[rs][1] = 1;//清空子区间*标记
        lazy[rt][2] = -1;
        return;
    }
    if (lazy[rt][1] != 1) {//乘法标记
        if (lazy[ls][2] != -1)//左子有等号标记改等号标记
            lazy[ls][2] = (lazy[ls][2] * lazy[rt][1]) % M;
        else {
            pushdown(lson);//清空标记
            lazy[ls][1] = (lazy[ls][1] * lazy[rt][1]) % M;//改乘法标记
        }
        if (lazy[rs][2] != -1)//右子有等号标记改等号标记
            lazy[rs][2] = (lazy[rs][2] * lazy[rt][1]) % M;
        else {
            pushdown(rson);//清空标记
            lazy[rs][1] = (lazy[rs][1] * lazy[rt][1]) % M;
        }
        lazy[rt][1] = 1;
    }
    if (lazy[rt][0]) {//加法标记
        if (lazy[ls][2] != -1)//同上
            lazy[ls][2] = (lazy[ls][2] + lazy[rt][0]) % M;
        else {
            pushdown(lson);
            lazy[ls][0] = (lazy[ls][0] + lazy[rt][0]) % M;
        }
        if (lazy[rs][2] != -1)
            lazy[rs][2] = (lazy[rs][2] + lazy[rt][0]) % M;
        else {
            pushdown(rson);
            lazy[rs][0] = (lazy[rs][0] + lazy[rt][0]) % M;
        }
        lazy[rt][0] = 0;
    }
}

void update(int opt, int L, int R, int v, int l, int r, int rt) {//更新任务
    if (L <= l && r <= R) {
        if (opt == 1) {//加法
            if (lazy[rt][2] != -1)
                lazy[rt][2] = (lazy[rt][2] + v % M) % M;
            else {
                pushdown(l, r, rt);
                lazy[rt][0] = (lazy[rt][0] + v % M) % M;
            }
        }
        else if (opt == 2) {//乘法
            if (lazy[rt][2] != -1)
                lazy[rt][2] = (lazy[rt][2] * v % M) % M;
            else {
                pushdown(l, r, rt);
                lazy[rt][1] = (lazy[rt][1] * v % M) % M;
            }
        }
        else {
            lazy[rt][2] = v % M;
            lazy[rt][0] = 0;
            lazy[rt][1] = 1;
        }
        return;
    }
    pushdown(l, r, rt);
    int mid = (l + r) >> 1;
    if (L <= mid)update(opt, L, R, v, lson);
    if (R > mid)update(opt, L, R, v, rson);
}
int query(int L, int R, int v, int l, int r, int rt) {//询问任务
    if (L <= l && r <= R && lazy[rt][2] != -1) {//此段下数字相同
        int temp = 1;
        while (v--)//v次方
            temp = (temp * lazy[rt][2]) % M;
        return (temp * (r - l + 1) % M) % M;
    }
    pushdown(l, r, rt);
    int mid = (l + r) >> 1;
    int ans = 0;
    if (L <= mid)ans = (ans + query(L, R, v, lson)) % M;
    if (R > mid)ans = (ans + query(L, R, v, rson)) % M;
    return ans;
}
int main() {
    int n, m;
    while (~scanf("%d%d", &n, &m)) {
        if (!n && !m)break;
        build(1, n, 1);
        while (m--) {
            int opt, x, y, c;
            scanf("%d%d%d%d", &opt, &x, &y, &c);
            if (opt < 4)
                update(opt, x, y, c, 1, n, 1);
            else
                printf("%d\n", query(x, y, c, 1, n, 1));
        }
    }
    return 0;
}
/*
5 5
3 3 5 7
1 2 4 4
4 1 5 2
2 2 5 8
4 3 5 3
0 0
*/

 

 
posted @ 2021-03-27 13:34  cono奇犽哒  阅读(62)  评论(0)    收藏  举报