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\n",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\n",t3.sum);
            }
        }
        else{
            int ans=t[1].sum;
            if(t[1].l==t[1].r&&ans>1)ans--;
            printf("%d\n",ans);
        }
    //    printf("%d %d %d %d\n",mov,rev,x,y);
    }
    return 0;
}
时间: 2024-10-14 03:20:54

bzoj1493[NOI2007]项链工厂 线段树的相关文章

BZOJ1493 NOI2007 项链工厂 线段树模拟

提交地址:http://www.lydsy.com/JudgeOnline/problem.php?id=1493 题目大意:给一个数列,进行一系列操作.包括旋转,翻转,改变等操作,以及查询颜色段数. 题目分析:数列中元素的相对位置没有改变,因此不需要用splay去做,而是可以用线段树解决这类问题. 旋转操作直接改变变量rotate,翻转操作用异或即可.每次询问先利用rotate求出当前1号位是谁,这样可以根据翻转标记确定区间.如果区间跨越n,那么合并的时候要考虑左边一段的右端和右边一段的左端.

BZOJ1493 [NOI2007]项链工厂

未完待续... 1493: [NOI2007]项链工厂 Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 1320  Solved: 576[Submit][Status][Discuss] Description T公司是一家专门生产彩色珠子项链的公司,其生产的项链设计新颖.款式多样.价格适中,广受青年人的喜爱. 最近T公司打算推出一款项链自助生产系统,使用该系统顾客可以自行设计心目中的美丽项链.该项链自助生产系 统包括硬件系统与软件系统,软件系统与

bzoj 1493: [NOI2007]项链工厂(线段树)

1493: [NOI2007]项链工厂 Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 1256  Solved: 545[Submit][Status][Discuss] Description Input 输 入文件第一行包含两个整数N, c,分别表示项链包含的珠子数目以及颜色 数目.第二行包含N 个整数,x1, x2…, xn,表示从位置1 到位置N 的珠子的颜色, 1 ≤ xi ≤ c.第三行包含一个整数Q,表示命令数目.接下来的Q 行每行一

【BZOJ-1493】项链工厂 Splay

1493: [NOI2007]项链工厂 Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 1440  Solved: 626[Submit][Status][Discuss] Description T公司是一家专门生产彩色珠子项链的公司,其生产的项链设计新颖.款式多样.价格适中,广受青年人的喜爱. 最近T公司打算推出一款项链自助生产系统,使用该系统顾客可以自行设计心目中的美丽项链.该项链自助生产系统包括硬件系统与软件系统,软件系统与用户进行交互并控制

【BZOJ 1493】[NOI2007]项链工厂

1493: [NOI2007]项链工厂 Time Limit: 30 Sec  Memory Limit: 64 MB Submit: 992  Solved: 454 [Submit][Status] Description   Input 输入文件第一行包含两个整数N, c,分别表示项链包含的珠子数目以及颜色 数目.第二行包含N 个整数,x1, x2-, xn,表示从位置1 到位置N 的珠子的颜色, 1 ≤ xi ≤ c.第三行包含一个整数Q,表示命令数目.接下来的Q 行每行一条命令, 如上

数据结构(Splay平衡树): [NOI2007] 项链工厂

[NOI2007] 项链工厂 ★★★   输入文件:necklace.in   输出文件:necklace.out   简单对比 时间限制:4 s   内存限制:512 MB [问题描述] T公司是一家专门生产彩色珠子项链的公司,其生产的项链设计新颖.款式多样.价格适中,广受青年人的喜爱.最近T公司打算推出一款项链自助生产系统,使用该系统顾客可以自行设计心目中的美丽项链. 该项链自助生产系统包括硬件系统与软件系统,软件系统与用户进行交互并控制硬件系统,硬件系统接受软件系统的命令生产指定的项链.该

NOI2007项链工厂——sbTreap代码

1 2 #include <iostream> 3 #include <cstdio> 4 #include <algorithm> 5 #include <cstring> 6 #include <cstdlib> 7 8 using namespace std; 9 struct node 10 { 11 int data; 12 int left; 13 int right; 14 int key; 15 int size; 16 bool

1493: [NOI2007]项链工厂

线段树. 真还就是个线段树.. 除去操作1,2的话,线段树很容易就处理了,问题在于如何处理操作1和2.(这点没想到).. 我们用一个delta维护操作1,如果没有旋转就+k,不然就-k. 每次读入i和j的时候用trans处理一下,就成功在O(1)的时间解决了操作1和2. 细节很重要. #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 2

BZOJ 1493 NOI2007 项链工厂

题目大意:维护一个环,每个点有一个颜色,提供6种操作: 1.将这个环顺时针旋转k 2.沿点1所在直径翻转 3.将两个珠子互换 4.将一段区间染色 5.查询这个环上有多少颜色段 6.查询一段区间有多少颜色段 关于颜色段通用的处理方法是每个区间记录三个值,颜色段数.左端点颜色.右端点颜色,合并时颜色段数相加,如果左区间右端点和右区间左端点颜色相同则减一 然后用Splay维护区间即可 不过这题还是有一些小细节需要处理 首先null节点要保证不会被修改 然后更新的时候特判 如果一段区间颜色是0直接返回另