http://acm.hdu.edu.cn/showproblem.php?pid=4902

出n个数,然后对这n个数进行两种操作:

如果是 1 l r x,则把 [l, r] 区间里面的每一个数都变为x;

如果是 2 l r x,则 比较 [l, r]区间里的数a_i和x的大小,如果a_i > x,把a_i变为a_i和x的最大公约数。

最后输出这n个数最终的值。

线段树可搞...但是没必要!...

线段树,每个结点多一个lazy表示该位置以下区间是否数字全相同,然后每次延迟操作,最后输出的时候单点查询即可

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;
#define RD(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define clr0(x) memset(x,0,sizeof(x))
typedef long long LL;
const int N = 100005; struct node
{
int lazy,v;
}s[N<<3];
int c[N];
void updata(int root){
s[root].v = max(s[root<<1].v,s[root<<1|1].v);
}
void build(int l,int r,int root)
{
s[root].lazy = 0;
if(l == r){
s[root].v = c[l];
return;
}
int mid = (l+r)>>1;
build(l,mid,root<<1);
build(mid+1,r,(root<<1)+1);
updata(root);
}
int gcd(int a,int b)
{
if(b==0)
return a;
return gcd(b,a%b);
}
void changee(int l,int r,int root,int ll,int rr,int v)
{
if (l > rr || r < ll) return;
if (ll <= l && rr >= r){
s[root].lazy = 1;
s[root].v = v;
return;
}
if(s[root].lazy){
s[root<<1].lazy = 1;
s[root<<1].v = s[root].v;
s[root<<1|1].lazy = 1;
s[root<<1|1].v = s[root].v;
s[root].lazy = 0;
}
int mid = (l+r)>>1;
changee(l,mid,root<<1,ll,rr,v);
changee(mid+1,r,(root<<1)+1,ll,rr,v);
updata(root);
}
void query(int l , int r , int root){
if(s[root].lazy || l == r){
for(int i = l;i <= r;++i)
printf("%d ",s[root].v);
return;
}
int mid = (l+r)>>1;
query(l,mid,root<<1);
query(mid+1,r,(root<<1)+1);
}
void change(int l , int r , int root, int ll , int rr , int x){
if (s[root].v < x || l > rr || r < ll) return;
if (s[root].lazy && ll <= l && rr >= r){
s[root].v = gcd(x,s[root].v);
return;
}
if(l == r){
s[root].v = gcd(x,s[root].v);
return;
}
if(s[root].lazy){
s[root<<1].lazy = 1;
s[root<<1].v = s[root].v;
s[root<<1|1].lazy = 1;
s[root<<1|1].v = s[root].v;
s[root].lazy = 0;
}
int mid = (l+r)>>1;
change(l,mid,root<<1,ll,rr,x);
change(mid+1,r,(root<<1)+1,ll,rr,x);
updata(root);
}
int main()
{
int Q,n,_;RD(_);
while(_--){
RD(n);
for(int i = 1;i <= n;++i)
RD(c[i]);
build(1,n,1);
RD(Q);
int l,r,q,x;
while(Q--){
scanf("%d%d%d%d",&q,&l,&r,&x);
if(q == 1)
changee(1,n,1,l,r,x);
else
change(1,n,1,l,r,x);
}
query(1,n,1);
puts("");
}
return 0;
}

其实逆向模拟即可,求每一个数的最终结果时,就可以用栈从后向前压入每个操作,直到遇到1操作,或者没有遇到1操作,则初值就为输入的a_i,然后把站内元素依次取出操作即可

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <iostream>
#include <algorithm>
using namespace std;
#define RD(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define clr0(x) memset(x,0,sizeof(x))
typedef long long LL;
const int maxn = 1e5+5;
struct opertion
{
int t, l, r;
int x;
}o[maxn];
int a[maxn];
int gcd(int a,int b)
{
if(b==0)
return a;
return gcd(b,a%b);
}
int main()
{
int _, n, i, j, Q;
RD(_);
while(_--) {
RD(n);
for(i = 1; i <= n; i++)
RD(a[i]);
RD(Q);
for(i = 0; i < Q; i++)
RD3(o[i].t,o[i].l,o[i].r),RD(o[i].x);
for(i = 1; i <= n; i++) {
stack<int> s;
int flag = 0;
for(j = Q - 1; j >= 0; j--) {
if(i >= o[j].l && i <= o[j].r) {
s.push(o[j].x);
if(o[j].t == 1) {
flag = 1;
break;
}
}
}
if(!flag) //没有遇到1操作
s.push(a[i]);
while(s.size() > 1) {
int ans = s.top(); s.pop();
int tmp = s.top(); s.pop();
if(ans > tmp)
ans = gcd(ans, tmp);
s.push(ans);
}
printf("%d ", s.top());
}
puts("");
}
return 0;
}

hdu 4902 线段树+逆向模拟的更多相关文章

  1. HDU 4902 (线段树)

    Problem Nice boat(HDU 4902) 题目大意 维护一个序列,两种操作. 第一种操作,将一段区间[l,r]赋值为x. 第二种操作,将一段区间[l,r]中大于等于x的数与x求gcd. ...

  2. hdu 1754 线段树(Max+单点修改)

    I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  3. hdu 5877 线段树(2016 ACM/ICPC Asia Regional Dalian Online)

    Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total ...

  4. hdu 3974 线段树 将树弄到区间上

    Assign the task Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  5. hdu 3436 线段树 一顿操作

    Queue-jumpers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To ...

  6. hdu 3397 线段树双标记

    Sequence operation Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  7. hdu 4578 线段树(标记处理)

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

  8. hdu 4533 线段树(问题转化+)

    威威猫系列故事——晒被子 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Tot ...

  9. hdu 2871 线段树(各种操作)

    Memory Control Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

随机推荐

  1. PAT 1002 写出这个数 (20)(代码)

    1002 写出这个数 (20)(20 分) 读入一个自然数n,计算其各位数字之和,用汉语拼音写出和的每一位数字. 输入格式:每个测试输入包含1个测试用例,即给出自然数n的值.这里保证n小于10^100 ...

  2. PHP 异步使用swoole的可行性测试

    PHP的异步.并行.高性能网络通信引擎swoole框架,在一开始我就比较注意,原因无他,php在swoole未出的情况下在多线程调度上确实算得上没有较好的解决方案. 我以系统的注册流程举例,在比较复杂 ...

  3. MySQL学习笔记-事务相关话题

    事务机制 事务(Transaction)是数据库区别于文件系统的重要特性之一.事务会把数据库从一种一致状态转换为另一个种一致状态.在数据库提交工作时,可以确保其要么所有修改都已经保存了,要么所有修改都 ...

  4. How to Disable/Enable IP forwarding in Linux

    This article describes how to Disable or Enable an IP forwarding in Linux. Current IP forwarding sta ...

  5. 如何获取堆的dump 的信息,如何分析

    获取方式: 1. jdk 自带启动参数 -XX:+HeapDumpBeforeFullGC -XX:HeapDumpPath=/x/x 产生dump日志,然后用visualVm分析 2. jmap 命 ...

  6. c#使用Stopwatch来计算时间间隔

    今天要记录一个接口的耗时情况,就要求去写一段测试各个代码运行时间的方法,于是就加了这么一段代码.原来的做法是在代码执行之前和之后获取系统时间,然后相减.被改成了使用c#里的Stopwatch来计算时间 ...

  7. 【机器学习】用Octave实现一元线性回归的梯度下降算法

    Step1 Plotting the Data 在处理数据之前,我们通常要了解数据,对于这次的数据集合,我们可以通过离散的点来描绘它,在一个2D的平面里把它画出来. 6.1101,17.592 5.5 ...

  8. 【Linux】开机自动启动脚本

    Linux下(以RedHat为范本)添加开机开机自动启动脚本有两种方式; 本例系统:Linux(CentOS 7.2) 方法一 使用 /etc/rc.d/rc.local,自动启动脚本 #!/bin/ ...

  9. mysql 5.7 linux环境下解压安装

    在CentOS linux环境安装mysql 一般rpm(或者yum),预编译和源码安装. 如果采用rpm或者yum安装,mysql的数据文件一般存放在/var/lib/mysql目录下,也就是会把d ...

  10. 【转】linux tar 压缩

    tar -c: 建立压缩档案-x:解压-t:查看内容-r:向压缩归档文件末尾追加文件-u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个.下面的 ...