题目大意:首先给你N个数,之后又两种操作:
一、1、l、r、x
把(l, r)上的数字变成x
二、2、l、r、x
吧(l,r)上的数字中大于(严格大于)x的数字变为这两个数字的GCD;
分析:线段树裸题;需要一点点剪枝不然会T。。。有人说暴力可过。。。。我线段树还T了一发佩服写暴力的大神;详细见代码:
/*Problem : 4902 ( Nice boat ) Judge Status : Accepted
RunId : 11728205 Language : G++ Author : Burglar
Code Render Status : Rendered By HDOJ G++ Code Render Version 0.01 Beta*/
#include
#include
#include
#include
#define MAXN 100005
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define LL long long
using namespace std;
struct Tree
{
LL max_num;//表示线段上最大的数字,用于剪枝
int lazy;//懒惰标记
int color;//判断线段上的数字是否相同,用于剪枝
}tree[MAXN << 2];
int n, m;
LL gcd(LL a, LL b)
{
if(a % b == 0) return b;
else
return gcd(b, a % b);
}
LL Max(LL a, LL b)
{
if(a > b) return a;
else
return b;
}
void PushUp(int rt)
{
if(tree[rt << 1].color && tree[rt << 1 | 1].color && tree[rt << 1].max_num == tree[rt << 1 | 1].max_num)
tree[rt].color = 1;
else
tree[rt].color = 0;
tree[rt].max_num = Max(tree[rt << 1].max_num, tree[rt << 1 | 1].max_num);
}
void PushDown(int rt)
{
if(tree[rt].lazy == 1)
{
tree[rt << 1].lazy = tree[rt << 1 | 1].lazy = tree[rt].lazy;
tree[rt << 1].max_num = tree[rt << 1 | 1].max_num = tree[rt].max_num;
tree[rt].lazy = 0;
}
}
void BuildTree(int l, int r, int rt)
{
tree[rt].lazy = 0;
tree[rt].color = 0;
if(l == r)
{
tree[rt].color = 1;
scanf("%I64d",&tree[rt].max_num);//这样子输入省时间,也省空间
return;
}
int m = (l + r) >> 1;
BuildTree(lson);
BuildTree(rson);
PushUp(rt);
}
void Update1(LL num, int ll, int rr, int l, int r, int rt)//第一种更新
{
if(ll <= l && r <= rr)
{
tree[rt].max_num = num;
tree[rt].lazy = 1;
return;
}
int m = (l + r) >> 1;
PushDown(rt);
if(ll <= m) Update1(num, ll, rr, lson);
if(rr > m) Update1(num, ll, rr, rson);
PushUp(rt);
}
void Update2(LL num, int ll, int rr, int l, int r, int rt)//第二种更新
{
if(ll <= l && r <= rr && tree[rt].max_num <= num) return;
if(ll <= l && r <= rr && tree[rt].max_num > num && tree[rt].color)
{
tree[rt].max_num = gcd(num, tree[rt].max_num);
tree[rt].lazy = 1;
return;
}
if(l == r)
{
if(tree[rt].max_num > num)
{
tree[rt].max_num = gcd(num, tree[rt].max_num);
}
return;
}
int m = (l + r) >> 1;
PushDown(rt);
if(ll <= m) Update2(num, ll, rr, lson);
if(rr > m) Update2(num, ll, rr, rson);
PushUp(rt);
}
LL query(int pos, int l, int r, int rt)//查询
{
if(l == r) return tree[rt].max_num;
int m = (l + r) >> 1;
PushDown(rt);
if(pos <= m) return query(pos, lson);
else
return query(pos, rson);
}
int main()
{
int t;
int type, l, r;
LL num;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
BuildTree(1, n, 1);
scanf("%d",&m);
for(int i = 0; i < m; i++)
{
scanf("%d%d%d%I64d",&type, &l, &r, &num);
if(type == 1)
{
Update1(num, l, r, 1, n, 1);
}
else
Update2(num, l, r, 1, n, 1);
}
for(int i = 1; i <= n; i++)
{
//我去这个输出的时候哪一行末尾是有空格的。。。这和说好的不一样啊,害我PE一发。。。
//if(i != 1) printf(" ");
printf("%I64d ",query(i, 1, n, 1));
}
printf("\n");
}
return 0;
}