2018 CCPC 吉林站 H Lovers

时间:2021-11-23 22:10:58

2018 CCPC 吉林站 H Lovers

传送门:https://www.spoj.com/problems/LIS2/en/

题意:

q次操作

1.将第l~r个数的左边和和右边都加上一个数d, 使得这个数变成 \(ds_id\)的形式

2.询问区间和

题解:

线段树题

这个update操作不好维护,我们来冷静分析一下

对于一个数x,他的长度为len,我们在他后面加上一个数d,那么他的长度就变成了len+1,这个数x就变成了\(x*10+d\)

同理,在前面加上一个数,这个数x就变成了\(d*10^{len(x)}+x\)

那么对于每次的update操作,我们需要更新,区间长度,区间和,左右添加的数,右边的标记每次要*10+d,左边的标记每次要加上len*val

下推标记时

要更新区间和,区间长度,左右标记,10的幂标记

注意取模问题

代码:

#include <set>
#include <map>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const int maxn = 3e5 + 5;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
LL sum1[maxn << 2];
LL sum2[maxn << 2];
LL lazy1[maxn << 2];
LL lazy2[maxn << 2];
LL lazylen[maxn << 2];
void push_up(int rt) {
sum1[rt] = (sum1[ls] + sum1[rs]) % mod;
sum2[rt] = (sum2[ls] + sum2[rs]) % mod;
}
void build(int l, int r, int rt) {
lazy1[rt] = lazy2[rt] = 0;
lazylen[rt] = 1;
sum1[rt] = r - l + 1;
sum2[rt] = 0;
if(l == r) return;
int mid = (l + r) >> 1;
build(lson);
build(rson);
push_up(rt);
}
void push_down(int l, int r, int rt) {
if(lazylen[rt] > 1) {
int mid = (l + r) >> 1; sum2[ls] = (lazy1[rt] % mod * sum1[ls] % mod * lazylen[rt] % mod +
sum2[ls] % mod * lazylen[rt] % mod +
lazy2[rt] % mod * 1LL * (mid - l + 1) % mod) % mod;
sum2[rs] = (lazy1[rt] % mod * sum1[rs] % mod * lazylen[rt] % mod +
sum2[rs] % mod * lazylen[rt] % mod +
lazy2[rt] % mod * 1LL * (r - mid) % mod) % mod; sum1[ls] = (sum1[ls] % mod * lazylen[rt] % mod * lazylen[rt] % mod) % mod;
sum1[rs] = (sum1[rs] % mod * lazylen[rt] % mod * lazylen[rt] % mod) % mod; lazy1[ls] = (lazy1[rt] % mod * lazylen[ls] % mod + lazy1[ls] % mod) % mod;
lazy1[rs] = (lazy1[rt] % mod * lazylen[rs] % mod + lazy1[rs] % mod) % mod; lazy2[ls] = (lazy2[ls] % mod * lazylen[rt] % mod + lazy2[rt] % mod) % mod;
lazy2[rs] = (lazy2[rs] % mod * lazylen[rt] % mod + lazy2[rt] % mod) % mod; lazylen[ls] = (lazylen[ls] % mod * lazylen[rt] % mod) % mod;
lazylen[rs] = (lazylen[rs] % mod * lazylen[rt] % mod) % mod; lazylen[rt] = 1;
lazy1[rt] = 0;
lazy2[rt] = 0;
}
}
void update(int L, int R, int val, int l, int r, int rt) {
if(L <= l && r <= R) {
sum2[rt] = (val % mod * sum1[rt] % mod * 10 % mod + sum2[rt] % mod * 10 % mod + (r - l + 1) % mod * val % mod) % mod;
sum1[rt] = (sum1[rt] % mod * 100) % mod;
lazy1[rt] = (lazylen[rt] % mod * val % mod + lazy1[rt] % mod) % mod;
lazy2[rt] = (lazy2[rt] % mod * 10 % mod + val % mod) % mod;
lazylen[rt] = (lazylen[rt] * 10) % mod;
return;
}
int mid = (l + r) >> 1;
push_down(l, r, rt);
if(L <= mid) update(L, R, val, lson);
if(R > mid) update(L, R, val, rson);
push_up(rt);
}
LL query(int L, int R, int l, int r, int rt) {
if(L <= l && r <= R) {
return sum2[rt];
}
int mid = (l + r) >> 1;
push_down(l, r, rt);
LL ans = 0;
if(L <= mid) ans = (ans + query(L, R, lson)) % mod;
if(R > mid) ans = (ans + query(L, R, rson)) % mod;
return ans % mod;
}
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
int T;
int cas = 1;
scanf("%d", &T);
while(T--) {
int n, m;
scanf("%d%d", &n, &m);
build(1, n, 1);
printf("Case %d:\n", cas++);
while(m--) {
char op[10];
scanf("%s", op);
if(op[0] == 'w') {
int l, r, d;
scanf("%d%d%d", &l, &r, &d);
update(l, r, d, 1, n, 1);
// debug2(n,m);
} else {
int l, r;
scanf("%d%d", &l, &r);
printf("%lld\n", query(l, r, 1, n, 1) % mod);
}
}
}
return 0;
}