hdu 4902

题目大意:首先给你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;
}


你可能感兴趣的:(线段树,线段树)