2018 ccpc 吉林 I.LOVERS(線段樹)

題意:初始化給定n個空串,每次有兩個操作:

  1. wrap l r d : change Si   To  dSid (l=<i<=r) 

  2. query l r :   \sum_{i=l}^{r} Si(mod\;1e9+7)

 題解:對於一個數字x若執行第一個操作則 x = d*10^{len(x)} + x*10 + d

則若對於一個區間sum(l,r)執行第一個操作則 sum(l,r) = 10*d*\sum_{i=l}^{r}10^{len(a[i])} + sum(l,r)*10 + d*(r-l+1) 

sumlen(l,r) = \sum_{i=l}^{r} 10^{len(a[i])} 則便可以用線段樹去維護這兩個東西便可,這裏只考慮了d是一位數的情況,但是在線段樹下傳標記的過程中可能一個區間多次執行第一個操作,那麼wrap的d便不是一位數,而且左右兩邊的d是鏡像的,我們便要用兩個lazy標記,lazy1維護左邊加的數,lazy2維護右邊加的數,同時可以用lazylen表示這兩個lazy的10^{len(lazy)},然後好好考慮一下如何維護sum和sumlen即可

 

#include<bits/stdc++.h>
using namespace std;
#define Sheryang main
#define TYPE int
const int maxn=2e5+7;
typedef long long ll;
const int mod=1e9+7;
void Smax(TYPE &a,TYPE b){if(a<b) a=b;}
void Smin(TYPE &a,TYPE b){if(a>b) a=b;}
///#define getchar()(p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
///char buf[(1 << 21) + 1], *p1 = buf, *p2 = buf;
#define IO cin.tie(0),ios::sync_with_stdio(false);
#define pi acos(-1)
#define PII pair<ll,ll>
ll read(){ll c = getchar(),Nig = 1,x = 0;while(!isdigit(c) && c!='-')c = getchar();if(c == '-')Nig = -1,c = getchar();while(isdigit(c))x = ((x<<1) + (x<<3)) + (c^'0'),c = getchar();return Nig*x;}
#define read read()
/** keep hungry and keep calm! **/

ll sum[maxn<<2],pos[maxn<<2],lazy1[maxn<<2],lazy2[maxn<<2],lazylen[maxn<<2];
// pos[rt] = 10^len(a[l]) + ... + 10^len(a[r])
int n;

void pushdown(int rt,int l,int r){
	if(lazylen[rt]>1){
		
		lazy1[rt<<1] = (lazy1[rt]*lazylen[rt<<1] + lazy1[rt<<1])%mod;
		lazy1[rt<<1|1] = (lazy1[rt]*lazylen[rt<<1|1] + lazy1[rt<<1|1])%mod;
		lazy2[rt<<1] = (lazy2[rt<<1]*lazylen[rt] + lazy2[rt])%mod;
		lazy2[rt<<1|1] = (lazy2[rt<<1|1]*lazylen[rt] + lazy2[rt])%mod;
		
		int mid = l+r>>1;
		sum[rt<<1] = lazy1[rt]*pos[rt<<1]%mod*lazylen[rt]%mod + sum[rt<<1]*lazylen[rt]%mod + lazy2[rt]*(mid-l+1)%mod;
		sum[rt<<1] %= mod;
		sum[rt<<1|1] = lazy1[rt]*pos[rt<<1|1]%mod*lazylen[rt]%mod + sum[rt<<1|1]*lazylen[rt]%mod + lazy2[rt]*(r-mid)%mod;
		sum[rt<<1|1] %= mod;
		
		pos[rt<<1] = (pos[rt<<1]*lazylen[rt]%mod*lazylen[rt])%mod;
		pos[rt<<1|1] = (pos[rt<<1|1]*lazylen[rt]%mod*lazylen[rt])%mod;
		
		lazylen[rt<<1] = (lazylen[rt<<1]*lazylen[rt])%mod;
		lazylen[rt<<1|1] = (lazylen[rt<<1|1]*lazylen[rt])%mod;
		
		lazy1[rt] = lazy2[rt] = 0;
		lazylen[rt] = 1;
	}
}

void pushup(int rt){
	pos[rt] = (pos[rt<<1] + pos[rt<<1|1])%mod;
	sum[rt] = (sum[rt<<1] + sum[rt<<1|1])%mod;
}

void build(int rt=1,int l=1,int r=n){
	sum[rt] = 0;
	lazy1[rt] = lazy2[rt] = 0;
	lazylen[rt] = 1;
	if(l==r){
		pos[rt] = 1;
		return;
	}
	int mid = l+r>>1;
	build(rt<<1,l,mid);
	build(rt<<1|1,mid+1,r);
	pushup(rt);
}

void Update(int l,int r,ll d,int L=1,int R=n,int rt=1){
	if(L>=l && R<=r){
		sum[rt] = (d*pos[rt]*10%mod+(R-L+1)*d%mod + 10*sum[rt]) %mod;
		pos[rt] = pos[rt]*100%mod;
		
		lazy1[rt] = (d*lazylen[rt]%mod + lazy1[rt]) %mod;
		lazylen[rt] = lazylen[rt]*10%mod;
		lazy2[rt] = (lazy2[rt]*10+d)%mod;
		pushdown(rt,L,R);
		return;
	}
	pushdown(rt,L,R);
	int mid = L+R>>1;
	if(l<=mid){
		Update(l,r,d,L,mid,rt<<1);
	}
	if(r>mid){
		Update(l,r,d,mid+1,R,rt<<1|1);
	}
	pushup(rt);
}

ll query(int l,int r,int L=1,int R=n,int rt=1){
	if(L>=l && R<=r){
		return sum[rt];
	}
	pushdown(rt,L,R);
	int mid = L+R>>1;
	ll ans = 0;
	if(l<=mid){
		ans = (ans + query(l,r,L,mid,rt<<1))%mod;
	}
	if(r>mid){
		ans = (ans + query(l,r,mid+1,R,rt<<1|1))%mod;
	}
	
	return ans;
}

int Sheryang(){
	
	int T=read;
	for(int Case=1 ; Case<=T ; Case++){
		n=read;
		int Q=read;
		
		build();
		printf("Case %d: \n",Case);
		
		while(Q--){
			char s[10];
			scanf("%s",s);
			if(s[0]=='w'){
				int l=read,r=read,val=read;
				Update(l,r,val);
			}else{
				int l=read,r=read;
				printf("%lld\n",query(l,r));
			}
		}
	} 
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章