hdu 5023 线段树 区间 2014广东区域赛网赛

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

当时大一学弟15minAC

搞得我压力山大 给队友写了

今天重新做了下,题还是很水  但是因为pushdown的时候if(l==r)return没有写  WA了一次

感觉到现在,简单的线段树已经可以随意点写了,就是按照自己的理解写,别慌,错了按树的结构思考下重新写

查询不知道pushdown所有的会不会超时,我的还是区间的查询,凡是子区间被修改过的结点,该节点pushdown后 其co值都被我改为0

然后就是vector存颜色,排序,去重输出

//#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <iomanip>
#include <cmath>
#include <map>
#include <set>
#include <queue>
using namespace std;

#define ls(rt) rt*2
#define rs(rt) rt*2+1
#define ll long long
#define ull unsigned long long
#define rep(i,s,e) for(int i=s;i<e;i++)
#define repe(i,s,e) for(int i=s;i<=e;i++)
#define CL(a,b) memset(a,b,sizeof(a))
#define IN(s) freopen(s,"r",stdin)
#define OUT(s) freopen(s,"w",stdout)
const ll ll_INF = ((ull)(-1))>>1;
const double EPS = 1e-8;
const double pi = acos(-1.0);
const int INF = 100000000;
const int MAXN = 1000000+100;

struct Node{
    int l,r;
    int co,flag;
}nodes[MAXN*4];

void build(int rt, int l, int r)
{
    nodes[rt].l=l;
    nodes[rt].r=r;
    nodes[rt].co=2;
    nodes[rt].flag=0;
    if(l == r)return;
    int mid=(l+r)/2;
    build(ls(rt),l,mid);
    build(rs(rt),mid+1,r);
}

void pushdown(int rt)
{
    if(nodes[rt].l == nodes[rt].r)return;
    if(nodes[rt].flag)
    {
        nodes[rs(rt)].co=nodes[ls(rt)].co=nodes[rt].co;
        nodes[ls(rt)].flag=nodes[rs(rt)].flag=1;
        nodes[rt].flag=0;
    }

}

void update(int rt, int l, int r, int cc)
{

    if(l<=nodes[rt].l && nodes[rt].r<=r)
    {
        pushdown(rt);
        nodes[rt].flag=1;
        nodes[rt].co=cc;
        return;
    }
    pushdown(rt);
    nodes[rt].co=0;
    int mid=(nodes[rt].l+nodes[rt].r)/2;
    if(l<=mid)update(ls(rt),l,r,cc);
    if(r>mid)update(rs(rt),l,r,cc);

}
vector<int>ans;

void query(int rt, int l, int r)
{
    ///
    //printf("nodes[rt].l=%d nodes[rt].r=%d l=%d r=%d co=%d\n",nodes[rt].l,nodes[rt].r,l,r,nodes[rt].co);
    //////.
    if(nodes[rt].l == nodes[rt].r)
    {
        if(nodes[rt].co)ans.push_back(nodes[rt].co);
        return ;
    }
    if(nodes[rt].l == l && nodes[rt].r==r && nodes[rt].co)
    {
        //pushdown(rt);
        ans.push_back(nodes[rt].co);
        return ;
    }
    pushdown(rt);
    int mid=(nodes[rt].l+nodes[rt].r)/2;
    if(r<=mid)query(ls(rt),l,r);
    else
    {
        if(l>mid)
            query(rs(rt),l,r);
        else
        {
            query(ls(rt),l,mid);
            query(rs(rt),mid+1,r);
        }
    }
}

int n,m;

int main()
{
    //IN("hdu5023.txt");
    char op[20];
    int l,r;
    while(~scanf("%d%d",&n,&m) && n+m)
    {
        build(1,1,n);
        while(m--)
        {
            scanf("%s%d%d",op,&l,&r);
            if(op[0] == 'P')
            {
                int cc;
                scanf("%d",&cc);
                update(1,l,r,cc);
            }
            else
            {
                ans.clear();
                query(1,l,r);
                sort(ans.begin(),ans.end());
                printf("%d",ans[0]);
                for(int i=1;i<ans.size();i++)
                {
                    if(ans[i]!=ans[i-1])printf(" %d",ans[i]);
                }
                putchar('\n');
            }
        }
    }
    return 0;
}
时间: 2024-10-18 00:19:31

hdu 5023 线段树 区间 2014广东区域赛网赛的相关文章

HDU 5023线段树区间染色,统计区间内颜色个数

这个也是一个线段树的模板 #include<iostream> #include<string.h> #include<algorithm> #include<stdio.h> #include<set> using namespace std; const int maxx = 1000050; set<int>s; struct node{ int color; int left; int right; int mid; }a[m

POJ 2777 &amp;&amp; ZOJ 1610 &amp;&amp;HDU 1698 --线段树--区间更新

直接将这3题 放一起了  今天在做线段树的东西 这3个都是区间更新的 查询方式互相不同 反正都可以放到一起吧 直接先上链接了 touch me touch me touch me 关于涉及到区间的修改 -- 区间更新的话 分为 增减 或者 修改 主要就是个 laze 标记 就是延迟更新 对于区间更新的写法 一般是有2种 其一 仔细划分到每个细小的区间    另一 粗略划分 反正 ==我的代码里会给出2种写法 看自己喜好 hdu 1 //线段树 成段更新 ---> 替换 根结点的查询 2 3 #i

HDU 4339 线段树区间合并

Query Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2573    Accepted Submission(s): 851 Problem Description You are given two strings s1[0..l1], s2[0..l2] and Q - number of queries.Your task

HDU 4578 线段树区间更新(确定区间操作的优先级)

HDU 4578 线段树区间更新 操作有: 区间所有数add(c) 区间所有数mul(c) 区间所有数set(c) 查询有: 区间所有数的p次方和(p>= 1 && p <= 3) 关键是区间更新的三种操作的优先级的确定清楚set>mul>add 关键是:down和update中对区间的更新操作是一回事,可以写成函数方便编程 //#pragma warning (disable: 4786) //#pragma comment (linker, "/STA

hdu 3308(线段树区间合并)

LCIS Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6069    Accepted Submission(s): 2635 Problem Description Given n integers.You have two operations:U A B: replace the Ath number by B. (index

HDU 3911 线段树区间合并

北京赛区快了,准备袭击数据结构和图论.倒计时 18天,线段树区间合并.维护一个最长连续.. 题意:给一个01串,以下有一些操作,问区间最长的连续的1的个数 思路:非常裸的线段树区间合并 #include<iostream> #include<cstdio> #include<map> #include<set> #include<cmath> #define lson id << 1 #define rson id <<

HDU5039--Hilarity DFS序+线段树区间更新 14年北京网络赛

题意:n个点的树,每个条边权值为0或者1, q次操作 Q 路径边权抑或和为1的点对数, (u, v)(v, u)算2个. M i修改第i条边的权值 如果是0则变成1, 否则变成0 作法: 我们可以求出每个点到根节点路径边权抑或和为val, 那么ans = val等于0的个数乘val等于1的个数再乘2. 注意到每一次修改操作,只会影响以u为根的子树(假设边为u----v  dep[v] > dep[u]), 那么每次只需把子树区间的值与1抑或就行了. 这一步可以用线段树区间更新. 比赛时过的人好少

hdu 5023 线段树延迟更新+状态压缩

/* 线段树延迟更新+状态压缩 */ #include<stdio.h> #define N 1100000 struct node { int x,y,yanchi,sum; }a[N*4]; int lower[31]; void build(int t,int x,int y) { a[t].x=x; a[t].y=y; a[t].yanchi=0; if(x==y){ a[t].sum=lower[1]; return ; } int temp=t<<1; int mid=

HDU 5316 线段树区间最值问题

T组数据 N个数字,M次操作 op=0:找出L-R区间内的最大'值' op=1:把a位置的数字换成b 对最大'值'的定义:取区间内的最大子序列,需要保证子序列的下标为奇偶交替的 用线段树分别记录每个区间的 ee:以偶数下标开始偶数下标结束的最大和 eo:以偶数下标开始奇数下标结束的最大和 oe:以奇数下标开始偶数下标结束的最大和 oo:以奇数下标开始奇数下标结束的最大和 对每次询问分别处理4种情况的最大值即可 修改时单点更新即可 #include "stdio.h" #include