码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2021-03-29 12:26:43      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:led   int   help   BMI   iss   ota   query   orm   result   

题目描述:

Transformation

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


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
思路:前三种操作都好说,主要是第四个次方的操作,这个没有特别的方法,只有暴力求,但是呢
这道题的第三个操作是把区间内的值设置为一样的,那如果操作四的时候查询的区间的值都是
一样的,那不就能只需要求一个数的次方,然后乘上区间长度(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
*/

 

 

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

标签:led   int   help   BMI   iss   ota   query   orm   result   

原文地址:https://www.cnblogs.com/MYMYACMer/p/14585573.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!