hdu 4578 Transformation(线段树)
线段树上的多操作。。。
题目大意:
树上 的初始值为0,然后有下列三种操作和求和。
1 x y c 在X-Y的之间全部加上C。
2 x y c 在X-Y的之间全部乘上C。
3 x y c 在X-Y之间的全部变成C。
4 x y c 输出在X-Y之间的所有数的C方的和。。。
思路:
因为存在两种不兼容的操作(如果直接放一起的话会出现顺序不同的影响,(3+2)*4 和 3*4+2 显然是不一样的)
所以每次合并操作的时候 就要把子树的操作推下去清除掉。
当然 如果这个区间的所有值都是一样的话。那么可以直接进行操作。
然后就是Query了。
因为要求出很多的平方 或者 立方和。
那么我们就去找所有区间的值是一样的区间。拿出来现乘方 再算有多少个。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#define lson num<<1,s,mid
#define rson num<<1|1,mid+1,e
#define maxn 100005
const int mod = 10007;
using namespace std; int add[maxn<<2];
int mul[maxn<<2];
int cov[maxn<<2];
int tre[maxn<<2];
int n,m; void pushdown(int num)
{
if(cov[num])//如果这个区间是值一样的
{
tre[num<<1]=tre[num<<1|1]=tre[num];
cov[num<<1]=cov[num<<1|1]=1;
add[num<<1]=add[num<<1|1]=0;
mul[num<<1]=mul[num<<1|1]=1;
cov[num]=0;
return;
}
if(add[num]!=0)//不一样的话 要把ADD推下去
{
if(cov[num<<1])
{
tre[num<<1]+=add[num];
tre[num<<1]%=mod;
}
else
{
pushdown(num<<1);
add[num<<1]+=add[num];
add[num<<1]%=mod;
} if(cov[num<<1|1])
{
tre[num<<1|1]+=add[num];
tre[num<<1|1]%=mod;
}
else
{
pushdown(num<<1|1);
add[num<<1|1]+=add[num];
add[num<<1|1]%=mod;
} add[num]=0;
}
if(mul[num]!=1)
{
if(cov[num<<1])
{
tre[num<<1]*=mul[num];
tre[num<<1]%=mod;
}
else
{
mul[num<<1]*=mul[num];
mul[num<<1]%=mod;
} if(cov[num<<1|1])
{
tre[num<<1|1]*=mul[num];
tre[num<<1|1]%=mod;
}
else
{
mul[num<<1|1]*=mul[num];
mul[num<<1|1]%=mod;
}
mul[num]=1;
}
} void build(int num,int s,int e)
{
add[num]=0;
mul[num]=1;
cov[num]=0;
tre[num]=0;
if(s==e)
{
cov[num]=1;
return;
}
int mid=(s+e)>>1;
build(lson);
build(rson);
} void update(int num,int s,int e,int l,int r,int val,int op)
{
if(l<=s && r>=e)
{
if(op==3)
{
add[num]=0;
mul[num]=1;
cov[num]=1;
tre[num]=val;
}
else
{
if(cov[num])
{
if(op==1)
{
tre[num]+=val;
tre[num]%=mod;
}
else
{
tre[num]*=val;
tre[num]%=mod;
}
}
else
{
pushdown(num); if(op==1)
{
add[num]+=val;
add[num]%=mod;
}
else
{
mul[num]*=val;
mul[num]%=mod;
}
}
}
return;
} pushdown(num); int mid=(s+e)>>1; if(l<=mid)update(lson,l,r,val,op);
if(r>mid)update(rson,l,r,val,op);
} int Q_Q(int num,int s,int e,int c)
{
printf("```%d\n",num);
int mid=(s+e)>>1;
if(cov[num]==1)
{
int tmp=1;
for(int aa=0;aa<c;aa++)
{
tmp*=tre[num];
tmp%=mod;
}
tmp*=(e-s+1);
tmp%=mod;
return tmp;
}
pushdown(num);
Q_Q(lson,c);
Q_Q(rson,c);
}
int query(int num,int s,int e,int l,int r,int c)
{
int mid=(s+e)>>1;
if(l==s && r==e)
{
if(cov[num])
{
int tmp=1;
while(c--)
{
tmp*=tre[num];
tmp%=mod;
}
tmp*=(e-s+1);
tmp%=mod;
return tmp;
}
}
pushdown(num); if(r<=mid)return query(lson,l,r,c);
else if(l>mid)return query(rson,l,r,c);
else return (query(lson,l,mid,c) + query(rson,mid+1,r,c))%mod;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0 && m==0)break;
int op,lef,rig,c;
build(1,1,n);
while(m--)
{
scanf("%d%d%d%d",&op,&lef,&rig,&c); if(op!=4)update(1,1,n,lef,rig,c,op);
else printf("%d\n",query(1,1,n,lef,rig,c)%mod);
}
}
return 0;
}
hdu 4578 Transformation(线段树)的更多相关文章
- HDU 4578 Transformation --线段树,好题
题意: 给一个序列,初始全为0,然后有4种操作: 1. 给区间[L,R]所有值+c 2.给区间[L,R]所有值乘c 3.设置区间[L,R]所有值为c 4.查询[L,R]的p次方和(1<=p< ...
- hdu 4578 Transformation 线段树
没什么说的裸线段树,注意细节就好了!!! 代码如下: #include<iostream> #include<stdio.h> #include<algorithm> ...
- hdu 4578 Transformation 线段树多种操作裸题
自己写了一个带结构体的WA了7.8次 但是测了几组小数据都对..感觉问题应该出在模运算那里.写完这波题解去对拍一下. 以后线段树绝不写struct!一般的struct都带上l,r 但是一条线段的长度确 ...
- Transformation HDU - 4578(线段树——懒惰标记的妙用)
Yuanfang is puzzled with the question below: There are n integers, a 1, a 2, …, a n. The initial val ...
- hdu 4031 attack 线段树区间更新
Attack Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others)Total Subm ...
- hdu 4288 离线线段树+间隔求和
Coder Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Su ...
- hdu 3016 dp+线段树
Man Down Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total S ...
- HDU 4578 - Transformation - [加强版线段树]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4578 Problem Description Yuanfang is puzzled with the ...
- HDU 4578 Transformation (线段树)
Transformation Time Limit: 15000/8000 MS (Java/Others) Memory Limit: 65535/65536 K (Java/Others)T ...
- HDU 4578——Transformation——————【线段树区间操作、确定操作顺序】
Transformation Time Limit: 15000/8000 MS (Java/Others) Memory Limit: 65535/65536 K (Java/Others)T ...
随机推荐
- operator.itemgetter的用法【转】
operator.itemgetter函数 operator模块提供的itemgetter函数用于获取对象的哪些维的数据,参数为一些序号(即需要获取的数据在对象中的序号),下面看例子. a = [,, ...
- Linux编译安装Darwin Streaming Server 6.0.3。。。
目前主流的流媒体服务器有微软的windows media server.RealNetworks的Helixserver和苹果公司的Darwin Streaming Server. 微软的window ...
- 3732 Ahui Writes Word
// N个物品 放进容量为C的背包里面 要求价值最大// 一看 第一反应是0 1背包 不过 N=100000 C=10000// 注意到 v,c在 10以内// 那么 最多就100种组合了 然后就转化 ...
- chrome console js多行输入
一直以来,Chrome控制台都缺少象IE调试台那样的多行执行模式. 今天意外发现Chrome其实也支持多行模式.默认在Chrome控制台上输入回车后会执行该命令,只需要通过输入Shift+Enter ...
- IPy的使用
IPy - class and tools for handling of IPv4 and IPv6 addresses and networks. Website: https://github. ...
- 链表的倒数第K个节点
题目:输入一个链表,输出该链表中倒数第K个节点.为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个结点. package com.edu; class LinkNode{ //定义一 ...
- Android欢迎界面的创建方法
1.制作一张启动图片splash.png,放置在res->drawable-hdpi文件夹中.2.新建布局文件splash.xml <?xml version="1.0" ...
- 程序破解之 API HOOK技术 z
API HOOK,就是截获API调用的技术,在程序对一个API调用之前先执行你的函数,然后根据你的需要可以执行缺省的API调用或者进行其他处理,假设如果想截获一个进程对网络的访问,一般是几个socke ...
- qt文本编辑器
示例代码: mainwindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include ...
- Cocos2d-x使用iOS游戏内付费IAP(C++篇)
本文章转载 http://www.ityran.com/archives/5515.非本人原创! 前期准备 设备与账号 在开始编码之前我们需要准备测试环境. IAP只能真机测试,准备一台iOS设备是必 ...