• bzoj1493[NOI2007]项链工厂 线段树


    1493: [NOI2007]项链工厂

    Time Limit: 30 Sec  Memory Limit: 64 MB
    Submit: 1712  Solved: 723
    [Submit][Status][Discuss]

    Description

    T公司是一家专门生产彩色珠子项链的公司,其生产的项链设计新颖、款式多样、价格适中,广受青年人的喜爱。

    最近T公司打算推出一款项链自助生产系统,使用该系统顾客可以自行设计心目中的美丽项链。该项链自助生产系

    统包括硬件系统与软件系统,软件系统与用户进行交互并控制硬件系统,硬件系统接受软件系统的命令生产指定的

    项链。该系统的硬件系统已经完成,而软件系统尚未开发,T公司的人找到了正在参加全国信息学竞赛的你,你能

    帮助T公司编写一个软件模拟系统吗?一条项链包含 N 个珠子,每个珠子的颜色是 1,2,…,c 中的一种。项链

    被固定在一个平板上,平板的某个位置被标记位置 1 ,按顺时针方向其他位置被记为 2,3,…,N。

    你将要编写的软件系统应支持如下命令:

    Input

    输入文件第一行包含两个整数 N,c ,分别表示项链包含的珠子数目以及颜色数目。

    第二行包含 N 个整数,x1,x2,…,xn ,表示从位置 1 到位置 N 的珠子的颜色,1≤xi≤c 。

    第三行包含一个整数 Q ,表示命令数目。接下来的 Q 行每行一条命令,如上文所述。N≤500000 ,Q≤500000,c≤1000 

    Output

    对于每一个 C 和 CS 命令,应输出一个整数代表相应的答案。

    Sample Input

    5 3
    1 2 3 2 1
    4
    C
    R 2
    P 5 5 2
    CS 4 1

    Sample Output

    4
    1

    HINT

    注意旋转命令旋转“珠子”但不改变“位置”的编号,而反转命令始终以位置 1 为对称轴。例如当 N=10 时,项

    链上的位置编号如图1:

    但注意此时项链上的位置编号仍然如图1所示,于是翻转的对称轴不变。因而再执行一次“F”命令时,项链的颜色

    如图4所示。

    2. 关于CountSegment命令CS命令表示查询一个“线段”中有多少个“部分”。尤其注意当查询的长度

    等于 N 时,我们仍然将查询部分作为“线段”理解。例如在图4所示的情况中,执行“CS 1 10”命令,查询从位

    置 1 开始到位置 10 结束的这个长度为 10 的线段中有多少个“部分”,于是得到返回值 3 。与之形成对照的是

    ,若执行“C”命令,返回值则为 2

    Source

    可以注意到不管项链怎么变,它上面颜色的相对位置不变,所以只要开全局变量记录变化就好
    维护线段树,常规区间操作,注意合并
    全局变量维护位置看
    http://blog.csdn.net/Regina8023/article/details/41697557

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #define ls u<<1
    #define rs ls|1
    #define ll long long
    #define N 500050
    using namespace std;
    int n,m,rev,mov,a[N];
    struct node{
        int lz,sum,l,r;
        node(){lz=sum=l=r=0;};
    }t[N<<2];
    void get(int &x,int &y){
        if(rev){x=n-x+2;y=n-y+2;}
        x-=mov;y-=mov;
        if(x<=0)x+=n;if(x>n)x-=n;
        if(y<=0)y+=n;if(y>n)y-=n;
    }
    node merge(node x,node y){
        node ret;
        ret.sum=x.sum+y.sum;
        if(x.r==y.l)ret.sum--;
        ret.l=x.l;ret.r=y.r;
        if(!ret.l)ret.l=y.l;
        if(!ret.r)ret.r=x.r;
        return ret;
    }
    void pushdown(int u){
        if(!t[u].lz)return;
        int x=t[u].lz;
        t[ls].lz=t[rs].lz=x;
        t[ls].l=t[ls].r=x;
        t[rs].l=t[rs].r=x;
        t[ls].sum=t[rs].sum=1;
        t[u].lz=0;
    }
    void build(int u,int l,int r){
        if(l==r){
            t[u].l=t[u].r=a[l];
            t[u].sum=1;return;
        }
        int mid=l+r>>1;
        build(ls,l,mid);
        build(rs,mid+1,r);
        t[u]=merge(t[ls],t[rs]);
    }
    void update(int u,int L,int R,int l,int r,int val){
        if(l<=L&&R<=r){
            t[u].l=t[u].r=t[u].lz=val;
            t[u].sum=1;return;
        }
        pushdown(u);
        int mid=L+R>>1;
        if(l<=mid)update(ls,L,mid,l,r,val);
        if(r>mid)update(rs,mid+1,R,l,r,val);
        t[u]=merge(t[ls],t[rs]);
    }
    node query(int u,int L,int R,int l,int r){
        if(l<=L&&R<=r)return t[u];
        pushdown(u);int mid=L+R>>1;
        node t1,t2;
        if(l<=mid)t1=query(ls,L,mid,l,r);
        if(r>mid)t2=query(rs,mid+1,R,l,r);
        return merge(t1,t2);
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
        build(1,1,n);
        char s[5];int x=0,y=0,z=0;
        scanf("%d",&m);
        while(m--){
            scanf("%s",s);
            if(s[0]=='R'){
                scanf("%d",&x);
                if(rev)mov-=x;
                else mov+=x;
                if(mov<0)mov+=n;
                if(mov>=n)mov-=n;
            }
            else if(s[0]=='F')rev^=1;
            else if(s[0]=='S'){
                scanf("%d%d",&x,&y);
                get(x,y);if(rev)swap(x,y);
                node t1=query(1,1,n,x,x);
                node t2=query(1,1,n,y,y);
                update(1,1,n,x,x,t2.l);
                update(1,1,n,y,y,t1.l);
            }
            else if(s[0]=='P'){
                scanf("%d%d%d",&x,&y,&z);
                get(x,y);if(rev)swap(x,y);
                if(x<=y)update(1,1,n,x,y,z);
                else{
                    update(1,1,n,x,n,z);
                    update(1,1,n,1,y,z);
                }
            }
            else if(s[0]=='C'&&s[1]=='S'){
                scanf("%d%d",&x,&y);
                get(x,y);if(rev)swap(x,y);
                if(x<=y)printf("%d
    ",query(1,1,n,x,y).sum);
                else{
                    node t1=query(1,1,n,x,n);
                    node t2=query(1,1,n,1,y);
                    node t3=merge(t1,t2);
                    printf("%d
    ",t3.sum);
                }
            }
            else{
                int ans=t[1].sum;
                if(t[1].l==t[1].r&&ans>1)ans--;
                printf("%d
    ",ans);
            }
        //    printf("%d %d %d %d
    ",mov,rev,x,y);
        }
        return 0;
    }

  • 相关阅读:
    Python实现将IP地址转换为数字
    转 python两个 list 获取交集,并集,差集的方法
    并发编程之协程
    网络编程之协议
    网络编程
    python之路-模块和包
    python IO模型
    python 线程(队列,线程池),协程(理论greenlet,gevent模块,)
    python 线程(部分)Thread的使用,守护线程,互斥锁,递归锁,信号量,事件,条件,定时器
    常见的面试题
  • 原文地址:https://www.cnblogs.com/wsy01/p/8064972.html
Copyright © 2020-2023  润新知