hdu 4902 Nice boat(线段树区间修改,输出最终序列)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4902

Problem Description

There is an old country and the king fell in love with a devil. The devil always asks the king to do some crazy things. Although the king used to be wise and beloved by his people. Now he is just like a boy in love and can’t refuse
any request from the devil. Also, this devil is looking like a very cute Loli.

Let us continue our story, z*p(actually you) defeat the ‘MengMengDa‘ party‘s leader, and the ‘MengMengDa‘ party dissolved. z*p becomes the most famous guy among the princess‘s knight party.

One day, the people in the party find that z*p has died. As what he has done in the past, people just say ‘Oh, what a nice boat‘ and don‘t care about why he died.

Since then, many people died but no one knows why and everyone is fine about that. Meanwhile, the devil sends her knight to challenge you with Algorithm contest.

There is a hard data structure problem in the contest:

There are n numbers a_1,a_2,...,a_n on a line, everytime you can change every number in a segment [l,r] into a number x(type 1), or change every number a_i in a segment [l,r] which is bigger than x to gcd(a_i,x) (type 2).

You should output the final sequence.

Input

The first line contains an integer T, denoting the number of the test cases.

For each test case, the first line contains a integers n.

The next line contains n integers a_1,a_2,...,a_n separated by a single space.

The next line contains an integer Q, denoting the number of the operations.

The next Q line contains 4 integers t,l,r,x. t denotes the operation type.

T<=2,n,Q<=100000

a_i,x >=0

a_i,x is in the range of int32(C++)

Output

For each test case, output a line with n integers separated by a single space representing the final sequence.

Please output a single more space after end of the sequence

Sample Input

1
10
16807 282475249 1622650073 984943658 1144108930 470211272 101027544 1457850878 1458777923 2007237709
10
1 3 6 74243042
2 4 8 16531729
1 3 4 1474833169
2 1 8 1131570933
2 7 9 1505795335
2 3 7 101929267
1 4 10 1624379149
2 2 8 2110010672
2 6 7 156091745
1 2 5 937186357

Sample Output

16807 937186357 937186357 937186357 937186357 1 1 1624379149 1624379149 1624379149 

Author

WJMZBMR

Source

2014 Multi-University Training Contest 4

题目意思:

给出长度为n的数组,m个操作,操作有两种:1、1, l, r, x即把[l,r]段的元素全变为x。2、2,l,r,x即把[l,r]段的大于x的元素全变成该元素与x的最大公约数。

代码如下:

#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;
#define LL long long
const int maxn = 111111;
#define ls (rt << 1)
#define rs (rt << 1 | 1)
#define lson l, mid, ls
#define rson mid+1, r, rs
//num数组表示该区间是否都是同一个数,如果是num就等于这个数,否则等-1
int num[maxn << 2];
//flag标记,表示该区间是否应该被纯色化(变成一个数)。
int flag[maxn << 2];
//mmax数组表示该区间的最大值,因为gcd只对该区间比x大的起作用
int mmax[maxn << 2];
int GCD(int a, int b)
{
	return a ? GCD(b%a,a) : b;
}
void Pushup(int rt)
{
	if(num[ls] == num[rs])
		num[rt] = num[ls];
	else
		num[rt] = -1;
	mmax[rt] = max(mmax[ls], mmax[rs]);
}

void Pushdown(int rt)
{
	if(flag[rt] != -1)
	{
		flag[ls] = flag[rs] = flag[rt];
		mmax[ls] = mmax[rs] = mmax[rt];
		num[ls] = num[rs] = num[rt];
		flag[rt] = -1;
	}
}

void build(int l, int r, int rt)
{
	flag[rt] = -1;
	if(l == r)
	{
		scanf("%d",&num[rt]);
		mmax[rt] = num[rt];//初始化
		return ;
	}
	int mid = (l+r) >> 1;
	build(lson);
	build(rson);
	Pushup(rt);
}

void update(int L, int R, int x, int l, int r, int rt)
{
	if(L <= l && r <= R)
	{
		flag[rt] = num[rt] = mmax[rt] = x;
		return ;
	}
	Pushdown(rt);
	int mid = (l+r) >> 1;
	if(L <= mid)
		update(L, R, x, lson);
	if(mid < R)
		update(L, R, x, rson);
	Pushup(rt);
}

void modify(int L, int R, int x, int l, int r, int rt)
{
	if(L <= l && r <= R && num[rt] > x)
	{
		flag[rt] = num[rt] = mmax[rt] = GCD(num[rt], x);
		return ;
	}
	Pushdown(rt);
	int mid = (l+r) >> 1;
	if(L <= mid && mmax[ls] > x)
		modify(L, R, x, lson);
	if(mid < R && mmax[rs] > x)
		modify(L, R, x, rson);
	Pushup(rt);
}

void Cout(int l, int r, int rt)
{
	if(l == r)
	{
		printf("%d ",num[rt]);
		return ;
	}
	Pushdown(rt);
	int mid = (l+r) >> 1;
	Cout(lson);
	Cout(rson);
}

int main()
{
	int T;
	int R, L;
	int n, m;
	int op,l, r, x;
	int i, j, k;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		build(1,n,1);
		scanf("%d",&m);
		for(i = 0; i < m; i++)
		{
			scanf("%d%d%d%d",&op,&l,&r,&x);
			if(op == 1)
			{
				update(l, r, x, 1, n, 1);
			}
			else if(op == 2)
			{
				modify(l, r, x, 1, n, 1);
			}
		}
		Cout(1, n, 1);
		printf("\n");
	}
	return 0;
}

hdu 4902 Nice boat(线段树区间修改,输出最终序列)

时间: 2024-12-22 00:15:09

hdu 4902 Nice boat(线段树区间修改,输出最终序列)的相关文章

HDU 4902 Nice boat --线段树(区间更新)

题意:给一个数字序列,第一类操作是将[l,r]内的数全赋为x ,第二类操作是将[l,r]中大于x的数赋为该数与x的gcd,若干操作后输出整个序列. 解法: 本题线段树要维护的最重要的东西就是一个区间内所有数是否相等的标记.只维护这个东西都可以做出来. 我当时想歪了,想到维护Max[rt]表示该段的最大值,最大值如果<=x的话就不用更新了,但是好像加了这个“优化”跑的更慢了. 我想大概是因为如果两个子树最大值或者整个两个子树的数不完全相等的话,根本不能直接下传这个值或者下传gcd,因为你不知道要更

HDU 4902 Nice boat(线段树)

HDU Nice boat 题目链接 题意:给定一个序列,两种操作,把一段变成x,把一段每个数字,如果他大于x,就变成他和x的gcd,求变换完后,最后的序列. 思路:线段树,每个结点多一个cover表示该位置以下区间是否数字全相同,然后每次延迟操作,最后输出的时候单点查询即可 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 1

多校第4场 HDU 4902 Nice boat 线段树

思路:这题比赛的时候宝哥说的思路我觉得对的,就是当是2操作的时候,先把数放到数组里,最后查询输出的时候再统一计算,不过那时敲得烂死了,debug了两天,靠-- 上午写的vector在pushDown的时候又忘了clear了,然后MLE了一早上,尼玛,还以为用的数组太大超了,然后又改成结构体,还是MLE,最后把别人的代码交上去发现没MLE,疯了一中午,最后无聊的时候才发现这个错误,尼玛--发现自己调试怎么变得这么弱了呢-- 还有一个需要注意的问题是1与2操作的处理上比较容易出错,这也是我WA了一下

HDU 5861 Road(线段树 区间修改 单点查询)

Road Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1132    Accepted Submission(s): 309 Problem Description There are n villages along a high way, and divided the high way into n-1 segments. E

HDU 4902 Nice boat 线段树+离线

据说暴力也过了.还傻逼地写了这么长. . . #include <stdio.h> #include <string.h> #include <math.h> #include <iostream> using namespace std; #define ll long long #define L(x) (x<<1) #define R(x) (x<<1|1) #define Val(x) tree[x].val #define

HDU - 1698 Just a Hook (线段树区间修改)

Description In the game of DotA, Pudge's meat hook is actually the most horrible thing for most of the heroes. The hook is made up of several consecutive metallic sticks which are of the same length. Now Pudge wants to do some operations on the hook.

hdoj 4901 The Romantic Hero DP hdoj 4902 Nice boat 线段树

惨遭丽洁乱虐..这一场也是比得乱七八糟的,4902本是丽洁定义比较难的题,结果数据随机的,被许多暴力水过了..4905考察的是四边形不等式优化,但是这道题的dp方程实际上不满足该优化的条件..朴素的o(n^3)会超时,所以这题目前是没有正解了..我还写了个这题的贪心,强度挺高,可以对大概一半数据,错的误差也只有个位数,还揪出官方第五个数据..朴素dp和贪心跑这个数据都比官方数据多了1,也就证明这题不满足四边形不等式优化的条件.. http://acm.hdu.edu.cn/showproblem

杭电 1698 Just a Hook(线段树区间修改)

http://acm.hdu.edu.cn/showproblem.php?pid=1698 Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 17322    Accepted Submission(s): 8640 Problem Description In the game of DotA, Pudge's

poj 2777 Count Color(线段树区间修改)

题目链接:http://poj.org/problem?id=2777 题目意思:就是问你在询问的区间里有几种不同的颜色 思路:这题和一般的区间修改差不多,但是唯一不同的就是我们要怎么计算有种颜色,所以这时候我们就需要把延时标记赋予不同的意义,当某段区间有多种颜色时就赋值为-1,当为一种颜色时就把它赋值为这个颜色的号数.这儿我们要怎么统计询问区间不同的颜色数叻,为了不重复计算同一种颜色,那么我们就需要用一个数组来标记计算过的颜色,当我们下次遇到时就不需要再次计算了.... 代码核心处就在计数那儿