线段树 + 区间更新 ----- HDU 4902 : Nice boat

Nice boat

Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 968    Accepted Submission(s): 441

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


【题目大意】

给你一串数字,有两个操作,1表示把一段区间内的数变成x,2表示把一段区间内的数如果这个数大于x则变为这个数与x的最小公约数,否则不变。最后输出变化后的一组数。

【题目分析】

这题和其他线段树有一些区别,这题是在所有的处理结束后才全部输出。
我们在每个结点中加一个flag标记该区间内的数字是否都是同一个,如果区间是同一个数的话我们就可以进行批处理,这将会大大降低时间复杂度。
再用一个temp来存储该结点的val,然后在pushdown函数将temp的值一层一层的传递下去。
这里的temp既起到了该结点是否已经向下更新的作用(相当于lazy),又起到了记录子节点需要更新的值的作用。
temp只有在val的值改变的时候才改变。

//Memory   Time
// 5376K     651MS
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<vector>
#include<queue>
#include<stack>
#include<iomanip>
#include<string>
#include<climits>
#include<cmath>
#define MAX 100100
#define LL long long
using namespace std;
int n,m;
int  ans;
int num[MAX];
struct Tree
{
    int l,r;
    bool flag;
    int val,temp;
};
Tree tree[MAX<<2];

int gcd(int x,int y)
{
    return y?gcd(y,x%y):x;
}

void pushup(int x)
{
    int tmp=x<<1;
    tree[x].val=max(tree[tmp].val,tree[tmp+1].val);
    tree[x].flag=(tree[tmp].val==tree[tmp+1].val&&tree[tmp].flag&&tree[tmp+1].flag);
}

void pushdown(int x)
{
    if(tree[x].temp==-1)return;
    int tmp=x<<1;
    int mid=(tree[x].l+tree[x].r)>>1;
    tree[tmp].val=tree[tmp+1].val=tree[tmp].temp=tree[tmp+1].temp=tree[x].temp;
    tree[x].temp=-1;
}

void build(int l,int r,int x)
{
    tree[x].flag=0;
    tree[x].temp=-1;
    tree[x].l=l,tree[x].r=r;
    if(l==r)
    {
        scanf("%d",&tree[x].val);
        tree[x].flag=1;
        return;
    }
    int tmp=x<<1;
    int mid=(l+r)>>1;
    build(l,mid,tmp);
    build(mid+1,r,tmp+1);
    pushup(x);
}

void update(int l,int r,int num,int x)
{
    if(r<tree[x].l||l>tree[x].r)return;
    if(l<=tree[x].l&&r>=tree[x].r)
    {
        tree[x].flag=1;
        tree[x].val=num;
        tree[x].temp=num;
        return;
    }
    pushdown(x);
    int tmp=x<<1;
    int mid=(tree[x].l+tree[x].r)>>1;
    if(r<=mid)
        update(l,r,num,tmp);
    else if(l>mid)
        update(l,r,num,tmp+1);
    else
    {
        update(l,mid,num,tmp);
        update(mid+1,r,num,tmp+1);
    }
    pushup(x);
}

void change(int l,int r,int num,int x)
{
    if(r<tree[x].l||l>tree[x].r)return;
    if(tree[x].flag&&tree[x].val<=num)return;
    if(l<=tree[x].l&&r>=tree[x].r&&tree[x].flag)
    {
        tree[x].val=gcd(tree[x].val,num);
        tree[x].temp=tree[x].val;
        return;
    }
    pushdown(x);
    int tmp=x<<1;
    int mid=(tree[x].l+tree[x].r)>>1;
    if(r<=mid)
        change(l,r,num,tmp);
    else if(l>mid)
        change(l,r,num,tmp+1);
    else
    {
        change(l,mid,num,tmp);
        change(mid+1,r,num,tmp+1);
    }
    pushup(x);
}

void query(int l,int r,int k,int x)
{
    if(k<tree[x].l||k>tree[x].r)return;
    if(tree[x].flag)
    {
        ans=tree[x].val;
        return;
    }
    pushdown(x);
    int tmp=x<<1;
    int mid=(tree[x].l+tree[x].r)>>1;
    if(k<=mid)
        query(l,mid,k,tmp);
    else
        query(mid+1,r,k,tmp+1);
}

int main()
{
    int T;
    int t,l,r,num;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        build(1,n,1);
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d %d %d %d",&t,&l,&r,&num);
            if(t==1)
                update(l,r,num,1);
            else
                change(l,r,num,1);
        }
        for(int i=1;i<=n;i++)
        {
            ans=0;
            query(1,n,i,1);
            printf("%d ",ans);
        }
        puts("");
    }
    return 0;
}

  


时间: 2024-10-19 01:01:57

线段树 + 区间更新 ----- HDU 4902 : Nice boat的相关文章

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

Nice boat 大意:给你一个区间,每次可以进行两种操作,1:把区间中的数全都变成x  2:把区间中大于x的数变成gcd(a[i], x),最后输出序列. 思路:线段树成段更行,用num数组的叶子存储数据,节点当作lazy来使用. 1 #include <stdio.h> 2 const int maxn = 100005; 3 4 int num[maxn<<2]; 5 6 int gcd(int a, int b){ 7 return b?gcd(b, a%b):a; 8

HDU 4902 Nice boat 2014杭电多校训练赛第四场F题(线段树区间更新)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4902 解题报告:输入一个序列,然后有q次操作,操作有两种,第一种是把区间 (l,r) 变成x,第二种是把区间 (l,r) 中大于x的数跟 x 做gcd操作. 线段树区间更新的题目,每个节点保存一个最大和最小值,当该节点的最大值和最小值相等的时候表示这个区间所有的数字都是相同的,可以直接对这个区间进行1或2操作, 进行1操作时,当还没有到达要操作的区间但已经出现了节点的最大值跟最小值相等的情况时,说明

Hdu 3966 Aragorn&#39;s Story (树链剖分 + 线段树区间更新)

题目链接: Hdu 3966 Aragorn's Story 题目描述: 给出一个树,每个节点都有一个权值,有三种操作: 1:( I, i, j, x ) 从i到j的路径上经过的节点全部都加上x: 2:( D, i, j, x ) 从i到j的路径上经过的节点全部都减去x: 3:(Q, x) 查询节点x的权值为多少? 解题思路: 可以用树链剖分对节点进行hash,然后用线段树维护(修改,查询),数据范围比较大,要对线段树进行区间更新 1 #include <cstdio> 2 #include

HDU 5023 A Corrupt Mayor&#39;s Performance Art 线段树区间更新+状态压缩

Link:  http://acm.hdu.edu.cn/showproblem.php?pid=5023 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <string> 7 #include <cmath> 8 using namesp

HDU 5023 A Corrupt Mayor&#39;s Performance Art(线段树区间更新)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5023 解题报告:一面墙长度为n,有N个单元,每个单元编号从1到n,墙的初始的颜色是2,一共有30种颜色,有两种操作: P a b c  把区间a到b涂成c颜色 Q a b 查询区间a到b的颜色 线段树区间更新,每个节点保存的信息有,存储颜色的c,30种颜色可以压缩到一个int型里面存储,然后还有一个tot,表示这个区间一共有多少种颜色. 对于P操作,依次往下寻找,找要更新的区间,找到要更新的区间之前

HDU 1698 Just a Hook (线段树,区间更新)

Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 17214    Accepted Submission(s): 8600 Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing f

HDU 1698 Just a Hook (线段树 区间更新基础)

Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 21856    Accepted Submission(s): 10963 Problem Description In the game of DotA, Pudge's meat hook is actually the most horrible thing

hdu 5023 A Corrupt Mayor&#39;s Performance Art(线段树区间更新)

#include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> using namespace std; int tree[5001000],add[5001000]; int color[50]; int n,m; void pushup(int pos) { tree[pos]=tree[pos<<1]|tree[pos<<1|1]; //更新

hdu 5023 A Corrupt Mayor&#39;s Performance Art (线段树+区间更新+状压)

A Corrupt Mayor's Performance Art Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others) Total Submission(s): 699    Accepted Submission(s): 267 Problem Description Corrupt governors always find ways to get dirty money.