• SDUT 3930 线段树


    皮卡丘的梦想2

    Time Limit: 1000MS Memory Limit: 65536KB

    Problem Description

    一天,一只住在 501 实验室的皮卡丘决定发奋学习,成为像 LeiQ 一样的巨巨,于是他向镇上的贤者金桔请教如何才能进化成一只雷丘。

    金桔告诉他需要进化石才能进化,并给了他一个地图,地图上有 n 个小镇,他需要从这些小镇中收集进化石。

    接下来他会进行 q 次操作,可能是打听进化石的信息,也可能是向你询问第 l 个小镇到第 r 个小镇之间的进化石种类。

    如果是打听信息,则皮卡丘会得到一个小镇的进化石变化信息,可能是引入了新的进化石,也可能是失去了全部的某种进化石。

    如果是向你询问,你需要回答他第 l 个小镇到第 r 个小镇之间的进化石种类。

    Input

    首先输入一个整数 T (1 <= T <= 10),代表有 T 组数据。

    每组数据的第一行输入一个整数 n (1 <= n <= 100000) 和一个整数 q (1 <= q <= 100000),分别代表有 n 个小镇,表皮卡丘有 q 次操作。

    接下来输入 q 行,对于每次操作,先输入操作类型,然后根据操作类型读入:

    • 1: 紧接着输入 2 个整数 a (1 <= a <= n), b (1 <= b <= 60),表示第 a 个小镇引入了第 b 种进化石
    • 2: 紧接着输入 2 个整数 a (1 <= a <= n), b (1 <= b <= 60),表示第 a 个小镇失去了全部第 b 种进化石
    • 3: 紧接着输入 2 个整数 l, r (1 <= l <= r <= n),表示他想询问从第 l 个到第 r 个小镇上可收集的进化石有哪几种

    Output

    对于每组输入,首先输出一行 "Case T:",表示当前是第几组数据。

    对于每组数据中的每次 3 操作,在一行中按编号升序输出所有可收集的进化石。如果没有进化石可收集,则输出一个 MeiK 的百分号 "%"(不包括引号)。

    Example Input

    1
    10 10
    3 1 10
    1 1 50
    3 1 5
    1 2 20
    3 1 1
    3 1 2
    2 1 50
    2 2 20
    3 1 2
    3 1 10

    Example Output

    Case 1:
    %
    50
    50
    20 50
    %
    %

     

    题意:

    有n个村庄,有最多60种石头,有三种操作:a b c ,a==1时表示b村庄加入第c种石头;a==2时表示b村庄移去第c种石头;a==3表示询问b到c村庄共有几种石头,输出石头的种类,如果没有石头输出%;

    输入t组数据

    输入n,m

    输入m行操作

    代码:

    //第一次见这种的线段树,做题还是太少了。
    //显然要用线段树,最多有60种石头,可以把他压缩一下,每个叶子节点存他有的石头的状态,更新时不过就是个位运算,
    //然后就是个水题了。
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int MAXN=400009;
    ll sum[MAXN];
    void pushup(int rt){
        sum[rt]=(sum[rt<<1]|sum[rt<<1|1]);
    }
    void build(int l,int r,int rt){
        if(l==r){
            sum[rt]=0;
            return;
        }
        int mid=(l+r)>>1;
        build(l,mid,rt<<1);
        build(mid+1,r,rt<<1|1);
        pushup(rt);
    }
    void update(int id,int f,int c,int l,int r,int rt){
        if(l==r){
            ll tmp=(1LL<<c);
            if(!(sum[rt]&tmp)&&f) sum[rt]|=tmp;
            else if((sum[rt]&tmp)&&!f) sum[rt]^=tmp;
            return;
        }
        int mid=(l+r)>>1;
        if(id<=mid) update(id,f,c,l,mid,rt<<1);
        else update(id,f,c,mid+1,r,rt<<1|1);
        pushup(rt);
    }
    ll query(int L,int R,int l,int r,int rt){
        if(L<=l&&R>=r)
            return sum[rt];
        ll ans=0;
        int mid=(l+r)>>1;
        if(L<=mid)
            ans|=query(L,R,l,mid,rt<<1);
        if(R>mid)
            ans|=query(L,R,mid+1,r,rt<<1|1);
        return ans;
    }
    int main()
    {
        int t,n,m;
        scanf("%d",&t);
        for(int cas=1;cas<=t;cas++){
            scanf("%d%d",&n,&m);
            int a,b,c;
            build(1,n,1);
            printf("Case %d:
    ",cas);
            for(int i=0;i<m;i++){
                scanf("%d%d%d",&a,&b,&c);
                if(a==1){
                    update(b,1,c-1,1,n,1);
                }
                else if(a==2){
                    update(b,0,c-1,1,n,1);
                }
                else if(a==3){
                    ll tmp=query(b,c,1,n,1);
                    int nu=0,cnt[64];
                    for(int i=0;i<60;i++){
                        if(tmp&(1LL<<i)) cnt[nu++]=i+1;
                    }
                    if(nu==0){
                        printf("%%
    ");
                        continue;
                    }
                    sort(cnt,cnt+nu);
                    for(int i=0;i<nu-1;i++)
                        printf("%d ",cnt[i]);
                    printf("%d
    ",cnt[nu-1]);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    渗透利器-kali工具 (第二章-4) 信息收集之目录扫描
    渗透利器-kali工具 (第二章-3) 信息收集之子域名扫描 -Sublist3
    渗透利器-kali工具 (第二章-2) 信息收集之端口扫描-NMAP
    渗透利器-kali工具 (第二章-1) 渗透测试流程以及信息收集总纲
    (4)top详解 (每周一个linux命令系列)
    (3)lscpu详解 (每周一个linux命令系列)
    (2)free详解 (每周一个linux命令系列)
    每周一个linux命令之---uptime详解
    使用python制作时间戳转换工具
    PSR规范0-4整理
  • 原文地址:https://www.cnblogs.com/--ZHIYUAN/p/6946232.html
Copyright © 2020-2023  润新知