2014 ACM/ICPC Asia Regional 广州网赛 | HDU 5023 & HDU 5024 & HDU 5025

HDU 5203:给定一段区间,初始颜色为2,你可以将一整段区间涂成某一种颜色,询问一段区间上的颜色数。

线段树操作。由于颜色最多只有30种,我们可以利用一个int来处理所有的颜色,向下用&运算,向上用|运算来合并所有颜色即可。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <map>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 1000100;

#define lc o<<1
#define rc o<<1|1

struct SegmentTree
{
    int color[maxn<<2];
    int setv[maxn<<2];
    
    int n;
    
    void init(int n)
    {
        this->n = n;
    }
    
    void pushup(int o)
    {
        color[o] = color[lc] | color[rc];
    }
    
    void build(int o, int L, int R)
    {
        color[o] = (1<<1); setv[o] = 2;
        if(L == R) return ;
        int M = L+(R-L)/2;
        build(lc, L, M);
        build(rc, M+1, R);
        pushup(o);
    }
    
    void pushdown(int o, int L, int R)
    {
        if(setv[o])
        {
            color[lc] = (1<<(setv[o]-1));
            color[rc] = (1<<(setv[o]-1));
            
            setv[lc] = setv[rc] = setv[o];
            setv[o] = 0;
        }
    }
    
    void update(int o, int L, int R, int y1, int y2, int v)
    {
        if(y1 <= L && y2 >= R)
        {
            color[o] = (1<<(v-1));
            setv[o] = v;
            return ;
        }
        
        int M = L+(R-L)/2;
        pushdown(o, L, R);
        
        if(y1 <= M) update(lc, L, M, y1, y2, v);
        if(y2 > M) update(rc, M+1, R, y1, y2, v);
        pushup(o);
    }
    
    int query(int o, int L, int R, int y1, int y2)
    {
        if(y1 <= L && y2 >= R) return color[o];
        
        int M = L+(R-L)/2;
        pushdown(o, L, R);
        
        int ans = 0;
        if(y1 <= M) ans |= query(lc, L, M, y1 ,y2);
        if(y2 > M) ans |= query(rc, M+1, R, y1, y2);
        return ans;
    }
    
    void print(int o, int L, int R)
    {
        printf("%d ", color[o]);
        if(L == R) return ;
        
        int M = L+(R-L)/2;
        print(lc, L, M); print(rc, M+1, R);
    }
};

////////////////

void readint(int &x)
{
    char c = getchar();
    while(!isdigit(c)) c = getchar();
    
    x = 0;
    while(isdigit(c))
    {
        x = x*10+c-'0';
        c = getchar();
    }
}

void writeint(int x)
{
    if(x > 9) writeint(x/10);
    printf("%d", x%10);
}

SegmentTree g;
int n, m, c;

int main()
{
    while(~scanf("%d%d", &n, &m))
    {
        if(n == 0 && m == 0) break;
        g.init(n+10);
        g.build(1, 1, n);
        while(m--)
        {
            char cmd[10]; int x, y, z;
            scanf("%s", cmd);
            if(cmd[0] == 'P')
            {
                readint(x), readint(y), readint(z);
                if(x > y)
                    swap(x, y);
                g.update(1, 1, n, x, y, z);
            }
            else if(cmd[0] == 'Q')
            {
                readint(x), readint(y);
                if(x > y)
                    swap(x, y);
                int tmp = g.query(1, 1, n, x, y);
                
                int ans = 1;
                
                while(tmp)
                {
                    if(tmp & 1 && tmp/2 != 0) writeint(ans), putchar(' ');
                    else if(tmp & 1) writeint(ans), puts("");
                    tmp >>= 1;
                    ans++;
                }
            }
        }
    }
    return 0;
}

HDU 5204:给定一个迷宫,求最长的一条路径,该路径上任意一点都可以通过最多不超过一次的转弯到达。

 

继续阅读