题意: 给一个序列,初始全为0,然后有4种操作:

1. 给区间[L,R]所有值+c

2.给区间[L,R]所有值乘c

3.设置区间[L,R]所有值为c

4.查询[L,R]的p次方和(1<=p<=3)

解法: 线段树,维护三个标记,addmark,mulmark,setmark分别表示3种更新,然后p[1],p[2],p[3]分别表示该节点的1,2,3次方和。标记传递顺序setmark一定是第一个,因为setmark可以使mulmark,addmark都失效还原,mulmark和addmark的顺序倒是无所谓。

这题写了半个比赛时间,写的很迷,还是没写出来, 后来看了别人写的,才知道自己很多地方都没更新好甚至没更新。这题算是一道线段树的综合题了,混合了几种常见的更新,对线段树的整体把握很有帮助。

比如:

1.如果setmark有值,那么addmark,mulmark全部要还原。

2.如果mulmark有值,那么addmark也要更新,更新为addmark*mulmark

就是这两点一直没考虑到,WA了好久。

在addmark下传过程中更新p[1],p[2],p[3]的方法如下:

比如 a^3 -> (a+c)^3 的过程:  (a+c)^3 = a^3 + c^3 + 3a*c^2 + 3*a^2*c, a是变量, 所以提取出c,那么p[3]可以由p[1],p[2]推出,p[2]可以由p[1]推出。

即 p[3] = p[3] + c^3 + 3*c^2*p[1] + 3*c*p[2] .

p[2]同理可以由p[1]推出。

然后每次都做一下pushdown,就可以得出正确答案。

当时像优化一下,少做几次pushdown,即这次的操作类型与上次一样就不pushdown,结果那样就会出现问题,还不如每次都pushdown呢。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define Mod 10007
#define SMod 10007
using namespace std;
#define N 100017 struct node{
int p[];
int setmark,addmark,mulmark;
}tree[*N]; void pushup(int rt){
for(int i=;i<=;i++) tree[rt].p[i] = (tree[*rt].p[i] + tree[*rt+].p[i])%SMod;
} void pushdown(int l,int r,int rt)
{
int mid = (l+r)/;
if(tree[rt].setmark)
{
int mk = tree[rt].setmark;
tree[rt<<].setmark = tree[rt<<|].setmark = mk;
tree[rt<<].addmark = tree[rt<<|].addmark = ;
tree[rt<<].mulmark = tree[rt<<|].mulmark = ; tree[rt<<].p[] = (mid-l+)%Mod*mk%SMod;
tree[rt<<|].p[] = (r-mid)%Mod*mk%SMod; tree[rt<<].p[] = (mid-l+)%Mod*mk%SMod*mk%SMod;
tree[rt<<|].p[] = (r-mid)%Mod*mk%SMod*mk%SMod; tree[rt<<].p[] = (mid-l+)%Mod*mk%SMod*mk%SMod*mk%SMod;
tree[rt<<|].p[] = (r-mid)%Mod*mk%SMod*mk%SMod*mk%SMod;
tree[rt].setmark = ;
}
if(tree[rt].mulmark != )
{
int mk = tree[rt].mulmark;
tree[rt<<].mulmark *= mk, tree[rt<<].mulmark%=SMod;
tree[rt<<|].mulmark *= mk, tree[rt<<|].mulmark%=SMod; tree[rt<<].addmark = tree[rt<<].addmark%SMod*mk%SMod;
tree[rt<<|].addmark = tree[rt<<|].addmark%SMod*mk%SMod; tree[rt<<].p[] = tree[rt<<].p[]%Mod*mk%SMod;
tree[rt<<|].p[] = tree[rt<<|].p[]%Mod*mk%SMod; tree[rt<<].p[] = tree[rt<<].p[]%Mod*mk%SMod*mk%SMod;
tree[rt<<|].p[] = tree[rt<<|].p[]%Mod*mk%SMod*mk%SMod; tree[rt<<].p[] = tree[rt<<].p[]%Mod*mk%SMod*mk%SMod*mk%SMod;
tree[rt<<|].p[] = tree[rt<<|].p[]%Mod*mk%SMod*mk%SMod*mk%SMod;
tree[rt].mulmark = ;
}
if(tree[rt].addmark)
{
int mk = tree[rt].addmark;
tree[rt<<].addmark += mk, tree[rt<<].addmark%SMod;
tree[rt<<|].addmark += mk, tree[rt<<|].addmark%SMod; tree[rt<<].p[] = (tree[rt<<].p[]%Mod + (mid-l+)%Mod*mk%SMod*mk%SMod*mk%SMod + *mk%Mod*tree[rt<<].p[]%SMod + *mk%SMod*mk%SMod*tree[rt<<].p[]%SMod)%SMod;
tree[rt<<|].p[] = (tree[rt<<|].p[]%Mod + (r-mid)%Mod*mk%SMod*mk%SMod*mk%SMod + *mk%Mod*tree[rt<<|].p[]%SMod + *mk%SMod*mk%SMod*tree[rt<<|].p[]%SMod)%SMod; tree[rt<<].p[] = (tree[rt<<].p[]%Mod + (mid-l+)%Mod*mk%SMod*mk%SMod + *mk%Mod*tree[rt<<].p[]%SMod)%SMod;
tree[rt<<|].p[] = (tree[rt<<|].p[]%Mod + (r-mid)%Mod*mk%SMod*mk%SMod + *mk%Mod*tree[rt<<|].p[]%SMod)%SMod; tree[rt<<].p[] = (tree[rt<<].p[]%Mod + (mid-l+)%Mod*mk%SMod)%SMod;
tree[rt<<|].p[] = (tree[rt<<|].p[]%Mod + (r-mid)%Mod*mk%SMod)%SMod;
tree[rt].addmark = ;
}
} void build(int l,int r,int rt)
{
tree[rt].setmark = tree[rt].addmark = ;
tree[rt].mulmark = ;
memset(tree[rt].p,,sizeof(tree[rt].p));
if(l == r) return;
int mid = (l+r)/;
build(l,mid,rt<<);
build(mid+,r,rt<<|);
} void update(int l,int r,int aa,int bb,int tag,int val,int rt) //tag = 3 : set 2:mul 1: add
{
if(aa <= l && bb >= r)
{
if(tag == )
{
tree[rt].p[] = (r-l+)%Mod*val%SMod;
tree[rt].p[] = (r-l+)%Mod*val%SMod*val%SMod;
tree[rt].p[] = (r-l+)%Mod*val%SMod*val%SMod*val%SMod;
tree[rt].setmark = val;
tree[rt].addmark = ;
tree[rt].mulmark = ;
}
else if(tag == )
{
tree[rt].p[] = tree[rt].p[]%SMod*val%SMod;
tree[rt].p[] = tree[rt].p[]%SMod*val%SMod*val%SMod;
tree[rt].p[] = tree[rt].p[]%SMod*val%SMod*val%SMod*val%SMod;
tree[rt].mulmark = tree[rt].mulmark%SMod*val%SMod;
tree[rt].addmark = tree[rt].addmark%SMod*val%SMod;
}
else if(tag == )
{
tree[rt].p[] = (tree[rt].p[]%SMod + (r-l+)%SMod*val%SMod*val%SMod*val%SMod + *val%SMod*tree[rt].p[]%SMod + *val%SMod*val%SMod*tree[rt].p[]%SMod)%SMod;
tree[rt].p[] = (tree[rt].p[]%SMod + (r-l+)%SMod*val%SMod*val%SMod + *val%SMod*tree[rt].p[]%SMod)%SMod;
tree[rt].p[] = (tree[rt].p[]%SMod + (r-l+)%SMod*val%SMod)%SMod;
tree[rt].addmark = (tree[rt].addmark+val)%SMod;
}
return;
}
int mid = (l+r)/;
pushdown(l,r,rt);
if(aa <= mid) update(l,mid,aa,bb,tag,val,rt<<);
if(bb > mid) update(mid+,r,aa,bb,tag,val,rt<<|);
pushup(rt);
} int query(int l,int r,int aa,int bb,int i,int rt)
{
if(aa > r || bb < l) return ;
if(aa <= l && bb >= r)
return tree[rt].p[i];
pushdown(l,r,rt);
int res = ;
int mid = (l+r)/;
return (query(l,mid,aa,bb,i,rt<<)%SMod+query(mid+,r,aa,bb,i,rt<<|)%SMod)%SMod;
} int main()
{
int n,m,i,j,op,x,y,c;
while(scanf("%d%d",&n,&m)!=EOF && n+m)
{
build(,n,);
while(m--)
{
scanf("%d%d%d%d",&op,&x,&y,&c);
if(op != ) update(,n,x,y,op,c,);
else printf("%d\n",query(,n,x,y,c,)%SMod);
}
}
return ;
}

HDU 4578 Transformation --线段树,好题的更多相关文章

  1. hdu 4578 Transformation 线段树多种操作裸题

    自己写了一个带结构体的WA了7.8次 但是测了几组小数据都对..感觉问题应该出在模运算那里.写完这波题解去对拍一下. 以后线段树绝不写struct!一般的struct都带上l,r 但是一条线段的长度确 ...

  2. hdu 4578 Transformation 线段树

    没什么说的裸线段树,注意细节就好了!!! 代码如下: #include<iostream> #include<stdio.h> #include<algorithm> ...

  3. Transformation HDU - 4578(线段树——懒惰标记的妙用)

    Yuanfang is puzzled with the question below: There are n integers, a 1, a 2, …, a n. The initial val ...

  4. Transformation 线段树好题 好题 (独立写出来对线段树不容易)

    Transformation Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 65535/65536 K (Java/Others)T ...

  5. HDU 4747 Mex ( 线段树好题 + 思路 )

    参考:http://www.cnblogs.com/oyking/p/3323306.html 相当不错的思路,膜拜之~ 个人理解改日补充. #include <cstdio> #incl ...

  6. hdu 1754 I Hate It 线段树基础题

    Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求, ...

  7. hdu 1754 I Hate It(线段树水题)

    >>点击进入原题测试<< 思路:线段树水题,可以手敲 #include<string> #include<iostream> #include<a ...

  8. HDU 1698 Just a Hook (线段树模板题-区间求和)

    Just a Hook In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of t ...

  9. [AHOI 2009] 维护序列(线段树模板题)

    1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec  Memory Limit: 64 MB Description 老师交给小可可一个维护数列的任务,现在小 ...

随机推荐

  1. 20个基于 WordPress 搭建的精美网站

    WordPress 无处不在,小到人博客,大到广受欢迎的各类特色网站,你都能发现 WordPress 的影子,因为它是创建和维护一个网站最容易使用的平台. 另外,网络上有很多资源来创建你的网站,你基本 ...

  2. Hadoop 2.5.1编译

    1.环境安装 gcc.gcc-c++.make.cmake.svn yum install lzo-devel zlib-devel gcc gcc-c++ make cmake autoconf a ...

  3. 升级tomcat7的运行日志框架到log4j2,可以打进kafka

    为了让web application能随意使用logging组件而不受web容器自身的影响,从tomcat 6.0开始,tomact默认使用的是java.util.logging framework来 ...

  4. android HorizontalScrollView

    第一个控件,借鉴网上的资料,自己稍加修改,横向滑动图片浏览功能,纪念下 布局文件 <?xml version="1.0" encoding="utf-8" ...

  5. iOS 单例传值遇见问题

    单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 1.单例模式的要点: 显然单例模式的要点有三个:一是某个类只能有一个实例: ...

  6. iOS关于CoreAnimation动画知识总结

    一:UIKit动画 在介绍CoreAnimation动画前先简单介绍一下UIKit动画,大部分简单的动画都可以使用UIKit动画实现,如果想实现更复杂的效果,则需要使用Core Animation了: ...

  7. ThreadLocal源码分析

    1.概述 ThreadLocal,可以理解为线程的局部变量,作用就是为每一个使用该变量的线程都提供一个变量值的副本,每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突. ThreadLo ...

  8. 资源list:Github上关于大数据的开源项目、论文等合集

    Awesome Big Data A curated list of awesome big data frameworks, resources and other awesomeness. Ins ...

  9. MongoDB Shard部署及Tag的使用

    Shard部署 准备测试环境 为准备数据文件夹 Cd  /home/tiansign/fanr/mongodb/Shard mkdir configdb1 configdb2 configdb3 mk ...

  10. Sqlite学习笔记(四)&&SQLite-WAL原理

    Sqlite学习笔记(三)&&WAL性能测试中列出了几种典型场景下WAL的性能数据,了解到WAL确实有性能优势,这篇文章将会详细分析WAL的原理,做到知其然,更要知其所以然. WAL是 ...