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

hdoj6562 Lovers(线段树)

时间:2019-07-17 15:26:42      阅读:81      评论:0      收藏:0      [点我收藏+]

标签:pow   左右   mes   span   str   一个   push   lld   函数   

传送:http://acm.hdu.edu.cn/showproblem.php?pid=6562

题意:有$n$个字符串,初始为空。$m$次操作,每次操作如下:

1. $wrap  l,r,d$ 代表给区间$[l,r]$内的每个字符串前后都加上数字$d$,即串变为$ds_id$;

2. $query  l,r$ 代表询问区间$[l,r]$内的和。

数据范围:

  $1 \le T \le 5, 1 \le n, m \le 1e5, 1 \le l \le r \le n.$

分析:

求区间和。(感觉是线段树,然后和学妹开始了漫漫路。可是没有树出来qaq

线段树每个结点维护:区间和$sum$,前缀的增量$lazy1$,后缀的增量$lazy2$,更新的长度$lazylen$,以及区间数值的长度$len$。

但是这里的更新长度和区间数值长度存储是表示为$10^k$,因为每次算贡献的时候这样方便计算,避免多次调用$pow$函数。

//开始考虑每增加一个$x$对于区间的影响:假设对于区间$[l,r]$增加了$x$。

对于前缀$lazy1$的影响:$lazy1=原有的更新长度lazylen*x+lazy1$

对于后缀$lazy2$的影响:$lazy2=lazy2*10+x$

对于区间和$sum$的影响:$sum=x*tree[root].len*10+(tree[root].r-tree[root].l+1)*x+tree[root].sum*10)$

对于区间更新长度$lazylen$:$lazylen*=10$

对于区间数值长度$len$:$len*=100$

然后每次需要把更新下传给左右儿子,然后取消他本身的更新标记。

每次$update$都需要$pushdown$和$pushup$。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=2e5+10;
 5 const int mod=1e9+7;
 6 struct node{
 7     ll l,r,sum;
 8     ll lazylen,lazy1,lazy2,len;
 9 }tree[maxn<<2];
10 ll ans;
11 void pushup(int root){
12     tree[root].len=(tree[root<<1].len+tree[root<<1|1].len)%mod;
13     tree[root].sum=(tree[root<<1].sum+tree[root<<1|1].sum)%mod;
14 }
15 void build(int root,int l,int r){
16     tree[root].l=l; tree[root].r=r;tree[root].sum=0;
17     tree[root].lazylen=1; tree[root].lazy1=0;tree[root].lazy2=0;tree[root].len=0;
18     if (l==r){
19         tree[root].len=1;
20         return ;
21     }
22     int mid=(l+r)>>1;
23     build(root<<1,l,mid);
24     build(root<<1|1,mid+1,r);
25     pushup(root);
26 }
27 void pushdown(int root){
28     if (tree[root].lazylen>1){
29         tree[root<<1].lazy1=(tree[root<<1].lazylen*tree[root].lazy1+tree[root<<1].lazy1)%mod;
30         tree[root<<1].lazy2=(tree[root<<1].lazy2*tree[root].lazylen+tree[root].lazy2)%mod;
31         tree[root<<1|1].lazy1=(tree[root<<1|1].lazylen*tree[root].lazy1+tree[root<<1|1].lazy1)%mod;
32         tree[root<<1|1].lazy2=(tree[root<<1|1].lazy2*tree[root].lazylen+tree[root].lazy2)%mod;
33         
34         tree[root<<1].sum=(tree[root].lazy1*tree[root<<1].len%mod*tree[root].lazylen%mod
35             +(tree[root<<1].r-tree[root<<1].l+1)*tree[root].lazy2%mod+tree[root<<1].sum*tree[root].lazylen)%mod;
36         tree[root<<1|1].sum=(tree[root].lazy1*tree[root<<1|1].len%mod*tree[root].lazylen%mod
37             +(tree[root<<1|1].r-tree[root<<1|1].l+1)*tree[root].lazy2%mod+tree[root<<1|1].sum*tree[root].lazylen)%mod;
38         
39         tree[root<<1].len=(tree[root<<1].len*tree[root].lazylen%mod*tree[root].lazylen)%mod;
40         tree[root<<1|1].len=(tree[root<<1|1].len*tree[root].lazylen%mod*tree[root].lazylen)%mod;
41         
42         tree[root<<1].lazylen=(tree[root<<1].lazylen*tree[root].lazylen)%mod;
43         tree[root<<1|1].lazylen=(tree[root<<1|1].lazylen*tree[root].lazylen)%mod;
44         
45         tree[root].lazy1=0;tree[root].lazy2=0;tree[root].lazylen=1;
46     }
47 }
48 
49 void update(int root,int l,int r,int x){
50     if (tree[root].l>=l && tree[root].r<=r){
51         tree[root].sum=(x*tree[root].len*10%mod+(tree[root].r-tree[root].l+1)*x%mod+tree[root].sum*10)%mod;
52         tree[root].len=(tree[root].len*100)%mod;
53         
54         tree[root].lazy1=(tree[root].lazylen*x+tree[root].lazy1)%mod;
55         tree[root].lazy2=(tree[root].lazy2*10+x)%mod;
56         tree[root].lazylen=tree[root].lazylen*10%mod;
57         pushdown(root);
58         return ;
59     }
60     pushdown(root);
61     int mid=(tree[root].l+tree[root].r)>>1;
62     if (mid>=l) update(root<<1,l,r,x);
63     if (mid<r) update(root<<1|1,l,r,x);
64     pushup(root);
65 }
66 void query(int root,int l,int r){
67     if (tree[root].l>=l && tree[root].r<=r){
68         (ans+=tree[root].sum)%=mod;
69         return ;
70     }
71     pushdown(root);
72     int mid=(tree[root].l+tree[root].r)>>1;
73     if (mid>=l) query(root<<1,l,r);
74     if (mid<r) query(root<<1|1,l,r);
75 }
76 int main(){
77     int t,n,m,x,y,z,_=0; scanf("%d",&t);
78     string s;
79     while (t--){
80         scanf("%d%d",&n,&m);
81         build(1,1,n);
82         printf("Case %d:\n",++_);
83         while (m--){
84             cin >> s;
85             if (s=="wrap"){
86                 scanf("%d%d%d",&x,&y,&z);
87                 update(1,x,y,z);
88             }
89             else{
90                 scanf("%d%d",&x,&y);
91                 ans=0;
92                 query(1,x,y);
93                 printf("%lld\n",ans);
94             }
95         } 
96     }
97     return 0;
98 }                                 

 

hdoj6562 Lovers(线段树)

标签:pow   左右   mes   span   str   一个   push   lld   函数   

原文地址:https://www.cnblogs.com/changer-qyz/p/11201188.html

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