---恢复内容开始---

传送门

参考资料:

  [1]:https://blog.csdn.net/mmk27_word/article/details/89788448

题目描述:
The Fool comes to a cross-road, filled with energy, confidence and purpose, knowing exactly where he wants to go and what he wants to do.
But he comes to a dead stop. A flowering tree marks the path he wants to take, the one he's been planning on taking. But standing before a fruit tree marking the other path is a woman.
The Fool has met and had relationships with women before, some far more beautiful and alluring.
But she is different. Seeing her, he feels as though he's just been shot in the heart with cupid's arrow.
(以上全是废话,与题意毫无关系) There are n empty strings:
s1,s2,...,sn.
You are required to perform two kinds of operations:
·wrap l r d : change si to dsid for all l <= i <= r,where d is a digit character;
·query l r : query ∑value(si)(mod 1e9+) (for all l <= i <= r),where value(s) is the number that string s represents. Note that the value of an empty string is . 输入
The first line contains one integer T, which denote the number of cases.
For each case, the first line contains two integer n and m where n is the number of strings and m is the number of operations.
Each line of the following m lines contains an operation with format (wrap l r d) or (query l r). 输出
For each case, you should output "Case i:" in a line, where i is the case number starting from .
Then for each query operation in that case, output a line that contains a single integer that representing the answer for that query operation.

题目描述

样例输入:

wrap
query wrap
wrap
query
query 样例输出
Case : Case :

样例输入输出

所有思路均来自参考资料,下面只是谈谈本蒟蒻的进一步理解:

  定义 f(s) = strlen(s);

  对串 s1 执行 swap 操作,可得到新串 ds1d,转换成数字就是 10*d*10f(s1)+s1*10+d;

  那么,对于区间[L,R]执行 swap 操作,其中的每个串 si 都会变成上述的形式;

  ∑(si) = 10*d*10f(sL)+sL*10+d + 10*d*10f(sL+1)+sL+1*10+d +..........+ 10*d*10f(sR)+sR*10+d

      = 10*d*( 10f(sL)+10f(sL+1)+..........10f(sR)+10*(sL+sL+1+.......+sR)+(R-L+1)*d;

  得出这个表达式后,就可以用线段树进行区间维护了;

  线段树中定义的变量 :

 struct Seg
{
int l,r;
ll f;
ll sum;
int mid(){return l+((r-l)>>);}
int len(){return r-l+;};
}seg[maxn<<];

  (f = 10f(sl)+10f(sl+1)+..........10f(sr)  , sum=∑(si) for all l  i ≤ r)

  那么,对于修改的区间[l,r],更新f,sum操作如下(假设当前要修改的节点为pos):

 seg[pos].sum=*d*seg[pos].f+*seg[pos].sum+seg[pos].len()*d;
seg[pos].f=seg[pos].f*;

  线段树处理区间修改问题一定要用到懒惰标记,如何标记呢?

 struct Seg
{
ll lazyLen;
ll lazyL;
ll lazyR;
int mid(){return l+((r-l)>>);}
int len(){return r-l+;};
}seg[maxn<<];

  (lazyL : 左边懒惰的值 , lazyR : 右侧懒惰的值 , lazyLen : 懒惰的长度)  

  令 val = seg[pos].sum;

  假设 pos 节点依次懒惰了 d1,d2,d3,那么 lazyL = d3d2d1 , lazyR = d1d2d3 , lazyLen = 1000(103,共懒惰了三位);

  pushDown(pos)向下传递懒惰标记函数如下:

 void F(int son,int f)
{
seg[son].sum=(seg[f].lazyL*seg[f].lazyLen%mod*seg[son].f%mod+
seg[son].sum*seg[f].lazyLen%mod+
seg[son].len()*seg[f].lazyR%mod)%mod;
seg[son].f=seg[son].f*seg[f].lazyLen%mod*seg[f].lazyLen%mod; seg[son].lazyL=(seg[f].lazyL*seg[son].lazyLen%mod+seg[son].lazyL)%mod;
seg[son].lazyR=(seg[son].lazyR*seg[f].lazyLen%mod+seg[f].lazyR)%mod;
seg[son].lazyLen=seg[son].lazyLen*seg[f].lazyLen%mod;
}
void pushDown(int pos)
{
Seg &tmp=seg[pos];
if(tmp.lazyLen <= )
return ; F(ls(pos),pos);
F(rs(pos),pos); tmp.lazyLen=;
tmp.lazyL=tmp.lazyR=;
}

 AC代码:

 #include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define ll long long
const int mod=1e9+;
const int maxn=1e5+; int n,m;
struct Seg
{
int l,r;
ll f;///10的幂和
ll sum;///区间和
ll lazyLen;
ll lazyL;///左侧懒惰的数
ll lazyR;///右侧懒惰的数
int mid(){return l+((r-l)>>);}
int len(){return r-l+;};
}seg[maxn<<]; void pushUp(int pos)
{
seg[pos].f=(seg[ls(pos)].f+seg[rs(pos)].f)%mod;
seg[pos].sum=(seg[ls(pos)].sum+seg[rs(pos)].sum)%mod;
}
void F(int son,int f)///向下传递懒惰标记
{
seg[son].sum=(seg[f].lazyL*seg[f].lazyLen%mod*seg[son].f%mod+
seg[son].sum*seg[f].lazyLen%mod+
seg[son].len()*seg[f].lazyR%mod)%mod;
seg[son].f=seg[son].f*seg[f].lazyLen%mod*seg[f].lazyLen%mod; seg[son].lazyL=(seg[f].lazyL*seg[son].lazyLen%mod+seg[son].lazyL)%mod;
seg[son].lazyR=(seg[son].lazyR*seg[f].lazyLen%mod+seg[f].lazyR)%mod;
seg[son].lazyLen=seg[son].lazyLen*seg[f].lazyLen%mod;
}
void pushDown(int pos)
{
Seg &tmp=seg[pos];
if(tmp.lazyLen <= )
return ; F(ls(pos),pos);
F(rs(pos),pos); tmp.lazyLen=;
tmp.lazyL=tmp.lazyR=;
}
void buildSegTree(int l,int r,int pos)
{
seg[pos].l=l;
seg[pos].r=r;
seg[pos].lazyLen=;
seg[pos].lazyL=seg[pos].lazyR=;
if(l == r)
{
seg[pos].f=;///初始为10^0
seg[pos].sum=;
return ;
}
int mid=l+((r-l)>>);
buildSegTree(l,mid,ls(pos));
buildSegTree(mid+,r,rs(pos)); pushUp(pos);
}
void Update(int l,int r,int pos,int d)
{
if(seg[pos].l == l && seg[pos].r == r)
{
seg[pos].sum=(*d*seg[pos].f%mod+*seg[pos].sum%mod+seg[pos].len()*d%mod)%mod;
seg[pos].f=seg[pos].f*%mod; seg[pos].lazyL=(d*seg[pos].lazyLen%mod+seg[pos].lazyL)%mod;
seg[pos].lazyR=(seg[pos].lazyR*+d)%mod;
seg[pos].lazyLen=seg[pos].lazyLen*%mod; return ;
}
pushDown(pos); int mid=seg[pos].mid();
if(r <= mid)
Update(l,r,ls(pos),d);
else if(l > mid)
Update(l,r,rs(pos),d);
else
{
Update(l,mid,ls(pos),d);
Update(mid+,r,rs(pos),d);
}
pushUp(pos);
}
ll Query(int l,int r,int pos)
{
if(seg[pos].l == l && seg[pos].r == r)
return seg[pos].sum; pushDown(pos); int mid=seg[pos].mid();
if(r <= mid)
return Query(l,r,ls(pos))%mod;///返回结果要取模
else if(l > mid)
return Query(l,r,rs(pos))%mod;
else
return (Query(l,mid,ls(pos))+Query(mid+,r,rs(pos)))%mod;
}
void Solve()
{
buildSegTree(,n,); for(int i=;i <= m;++i)
{
char order[];
int l,r,d;
scanf("%s%d%d",order,&l,&r);
if(order[] == 'w')
{
scanf("%d",&d);
Update(l,r,,d);
}
else
printf("%d\n",Query(l,r,));
}
}
int main()
{
int test;
scanf("%d",&test);
for(int kase=;kase <= test;++kase)
{
scanf("%d%d",&n,&m); printf("Case %d:\n",kase);
Solve();
}
return ;
}

刚开始,我的lazyLen记录的就是懒惰的长度,每次更新的时候都用个 quickPower(10,lazyLen),超时了..........

调用quickPower()的次数太多了,每次 wrap 操作都要用到好多个quickPower();

CCPC 2018 吉林 H "LOVERS" (线段树)的更多相关文章

  1. UVALive 8519 Arrangement for Contests 2017西安区域赛H 贪心+线段树优化

    题意 等价于给一个数列,每次对一个长度为$K$的连续区间减一 为最多操作多少次 题解: 看样例猜的贪心,10分钟敲了个线段树就交了... 从1开始,找$[i,i+K]$区间的最小值,然后区间减去最小值 ...

  2. HDU 4417 Super Mario(2012杭州网络赛 H 离线线段树)

    突然想到的节约时间的方法,感觉6翻了  给你n个数字,接着m个询问.每次问你一段区间内不大于某个数字(不一定是给你的数字)的个数 直接线段树没法做,因为每次给你的数字不一样,父节点无法统计.但是离线一 ...

  3. uoj#418. 【集训队作业2018】三角形(线段树合并)

    传送门 好迷啊--膜一下ljz 考虑每个操作,如果把操作按先后顺序放到序列上的话,操作一就是把\(w_i\)的石子放到某个节点,那么就是在序列末端加入\(w_i\),然后根据贪心肯定要把它所有儿子的石 ...

  4. hdu 5475 模拟计算器乘除 (2015上海网赛H题 线段树)

    给出有多少次操作 和MOD 初始值为1 操作1 y 表示乘上y操作2 y 表示除以第 y次操作乘的那个数 线段树的叶子结点i 表示 第i次操作乘的数 将1替换成y遇到操作2 就把第i个结点的值 替换成 ...

  5. 2017 CCPC 杭州 HDU6273J 区间修改(线段树&差分数组)

    http://acm.hdu.edu.cn/downloads/CCPC2018-Hangzhou-ProblemSet.pdf 解析 线段树区间延迟更新 或 差分数组 两个数   统计2和3的最少的 ...

  6. hdu 6562 Lovers (线段树)

    大意: 有$n$个数字串, 初始为空, 两种操作(1)把$[l,r]$范围的所有数字串首位添加数位$d$ (2)询问$[l,r]$区间和 假设添加的数为$L$, $L$位数为$H$, $L$翻转后乘上 ...

  7. UOJ 418 【集训队作业2018】三角形——思路+线段树合并

    题目:http://uoj.ac/problem/418 看了题解才会…… 很好的想法是把整个过程看成若干 “取一点 i ,值+=w[ i ],值-=\(\sum w[j]\)”(其中 j 是 i 的 ...

  8. CCPC 2018 吉林 C "JUSTICE" (数学)

    传送门 参考资料: [1]:https://blog.csdn.net/mmk27_word/article/details/89789770 题目描述 Put simply, the Justice ...

  9. HDU1754-ZKW线段树

    单点更新,区间最值 HDU 1754 // // Created by helica on 2018/3/18. // //zkw线段树 单点修改 区间求最值 //HDU 1754 #include ...

随机推荐

  1. IE8下的兼容小经验

    placeholder IE8下不支持HTML5属性placeholder,不过为解决此问题的js插件挺多的,比如:jquery-placeholder.也可以使用jquery来写. last-chi ...

  2. github中markdown语言的使用规则

    开始使用github就接触了markdown,确实如它的宗旨所言"易读易写",语法简洁明了,功能比纯文本更强,是一种非常适用于网络的书写语言.并且一大优点是兼容HTML,只要不在m ...

  3. getElementsByClassName兼容低版本浏览器

    var getElementsByClassName = function (searchClass, node,tag) { if(document.getElementsByClassName){ ...

  4. Effective C++: 08定制new和delete

    49:了解new-handler的行为 当operator new无法满足某一内存分配需求时,它会抛出异常(以前会返回一个null).在抛出异常之前,它会调用一个客户指定的错误处理函数,也就是所谓的n ...

  5. 使用Velero Restic快速完成云原生应用迁移至ACK集群

    本文记录使用Velero Restic快速完成云原生应用迁移至ACK集群的实践过程. 0. 实践步骤概览 (1)创建GKE集群(或自建Kubernetes集群)(2)在GKE集群上部署示例应用Jenk ...

  6. html5 拖放学习

    html5拖放 需要有可拖放元素,可放置的位置(可多个),就像是一个苹果,多个箱子,苹果可以在箱子间来回放置,同样元素也可在多个可放置位置间来回拖放. 如果只有一个位置,元素只可被从原位置托放置唯一目 ...

  7. Person Re-identification 系列论文笔记(三):Improving Person Re-identification by Attribute and Identity Learning

    Improving Person Re-identification by Attribute and Identity Learning Lin Y, Zheng L, Zheng Z, et al ...

  8. HDU_2035:人见人爱A^B

    Problem Description 求A^B的最后三位数表示的整数. 说明:A^B的含义是“A的B次方”   Input 输入数据包含多个测试实例,每个实例占一行,由两个正整数A和B组成(1< ...

  9. Android横竖屏切换和灭屏亮屏时Activity的生命周期探究(1)

    研究这个问题的初衷在于项目中碰到了一个问题:横屏的时候灭屏再亮屏,亮屏的时候用户能够清晰的看到先启动竖屏(过程1)再切换到横屏的过程,因为灭屏的时候onSaveInstanceState()保存的时横 ...

  10. Datagrid添加右键菜单 标签: 三层EasyUI 2015-08-14 19:57 1029人阅读 评论(22)

    最近的一个项目前台使用的EasyUI,每个界面都有DataGrid控件,按照我们的想法,应该做出来的效果是单击选中,双击可编辑,当然右键也应该出现这些菜单按钮,想的挺好,那么该如何实现呢?一开始不知道 ...