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.
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 */