[线段树]JZOJ 1214 项链工厂

Posted mastervan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[线段树]JZOJ 1214 项链工厂相关的知识,希望对你有一定的参考价值。

Description

  T 公司是一家专门生产彩色珠子项链的公司,其生产的项链设计新颖、款式多样、价格适中,广受青年人的喜爱。最近T 公司打算推出一款项链自助生产系统,使用该系统顾客可以自行设计心目中的美丽项链。
  该项链自助生产系统包括硬件系统与软件系统,软件系统与用户进行交互并控制硬件系统,硬件系统接受软件系统的命令生产指定的项链。该系统的硬件系统已经完成,而软件系统尚未开发,T 公司的人找到了正在参加全国信息学竞赛的你,你能帮助T 公司编写一个软件模拟系统吗?
  一条项链包含N 个珠子,每个珠子的颜色是1, 2, …, c 中的一种。项链被固定在一个平板上,平板的某个位置被标记位置1,按顺时针方向其他位置被记为2,3,…,N。   技术图片
  你将要编写的软件系统应支持如下命令:
  1.R k(0 < K < N) 意为Rotate k。将项链在平板上顺时针旋转k 个位置, 即原来处于位置1 的珠子将转至位置k+1,处于位置2 的珠子将转至位置k+2,依次类推。
  2. F 意为Flip。将平板沿着给定的对称轴翻转,原来处于位置1 的珠子不动,位置2 上的珠子与位置N 上的珠子互换,位置3 上的珠子与位置N-1 上的珠子互换,依次类推。
  3.S i j(1≤I,j≤N) 意为Swap i , j。将位置i 上的珠子与位置j 上的珠子互换。
  4.P I j x(1≤I,j≤N,x≤c) 意为Paint i , j , x。将位置i 沿顺时针方向到位置j 的一段染为颜色x。
  5.C 意为Count。查询当前的项链由多少个“部分”组成,我们称项链中颜色相同的一段为一个“部分”。
  6.CS i j(1≤I,j≤N) 意为CountSegment i , j。查询从位置i沿顺时针方向到位置j 的一段中有多少个部分组成。

 

Input

  输入文件第一行包含两个整数N, c,分别表示项链包含的珠子数目以及颜色数目。
第二行包含N 个整数,x1, x2…, xn,表示从位置1 到位置N 的珠子的颜色,1 ≤ xi ≤ c。
第三行包含一个整数Q,表示命令数目。
接下来的Q 行每行一条命令,如上文所述。

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

 

Data Constraint

 
 

Hint

【数据规模和约定】
  对于60%的数据,N ≤ 1 000,Q ≤ 1 000;
  对于100%的数据,N ≤ 500 000,Q ≤ 500 000,c ≤ 1 000。

分析

说实话一开始根本没想线段树,考虑到前面各种奇怪的操作,我想到的是splay

然后在查询卡壳了,不得已写了线段树

结果写爆了,样例死活过不去……最后交的链表暴力

正难则反,我们考虑做旋转和翻转时,我们不动数据结构本身,而是给输入的值做变换

旋转了k,相当于对称轴-k

而翻转,会影响三个:

对称轴的变换,会转为顺时针

查询和修改,会转为从对称轴往逆时针数,而且计算也要往逆时针数,要交换

然后不得不说这题细节真[嘟——]多

我还给自己挖了个细节跳:

CS的查询,说是从x节点往y节点顺时针计算不同的颜色端有多少个

我考虑到了x-1==y的情况,也就是把整个项链囊括在内,我以为这时候要减去x的颜色=y的颜色的情况

然鹅顺时针算出来的其实是一条链……

 

技术图片
#include <iostream>
#include <cstdio>
#include <memory.h>
#include <cstdlib>
#define lson (x<<1)
#define rson ((x<<1)+1)
using namespace std;
const int N=5e5+10;
struct Seg 
    int l,r,cnt,p;
t[4*N];
int rt=1,rv[N];
int n,c,q,a[N],dcz,rev;

void Update(int x) 
    t[x].l=t[lson].l,t[x].r=t[rson].r;
    t[x].cnt=t[lson].cnt+t[rson].cnt-(t[lson].r==t[rson].l);


void Pushdown(int x) 
    if (t[x].p) 
        t[lson].l=t[lson].r=t[rson].l=t[rson].r=t[lson].p=t[rson].p=t[x].p;
        t[lson].cnt=t[rson].cnt=1;
        t[x].p=0;
    


void Build(int x,int l,int r) 
    if (l==r) 
        t[x].l=t[x].r=a[l];
        rv[l]=x;t[x].cnt=1;
        return;
    
    int mid=l+r>>1;
    Build(lson,l,mid);
    Build(rson,mid+1,r);
    Update(x);


void Color(int x,int l,int r,int ll,int rr,int k) 
    if (rr<l||r<l||r<ll) return;
    if (ll<=l&&r<=rr) 
        t[x].l=t[x].r=t[x].p=k;
        t[x].cnt=1;
        return;
    
    int mid=l+r>>1;
    Pushdown(x);
    if (ll<=mid) Color(lson,l,mid,ll,rr,k);
    if (mid<rr) Color(rson,mid+1,r,ll,rr,k);
    Update(x);


int Query(int x,int l,int r,int ll,int rr) 
    if (rr<l||r<l||r<ll) return 0;
    if (ll<=l&&r<=rr) return t[x].cnt;
    int mid=l+r>>1,ans=0;
    int c1=0,c2=0;
    Pushdown(x);
    if (ll<=mid) c1=Query(lson,l,mid,ll,rr);
    if (mid<rr) c2=Query(rson,mid+1,r,ll,rr);
    if (c1&&c2) ans=c1+c2-(t[lson].r==t[rson].l);
    else ans=c1+c2;
    return ans;


int main() 
    scanf("%d%d",&n,&c);rev=1;dcz=1;
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    Build(rt,1,n);
    for (scanf("%d",&q);q;q--) 
        char ord[3];int x,y,z;
        memset(ord,0,sizeof ord);
        scanf("%s",ord);
        switch (ord[0]) 
            case R:
                scanf("%d",&x);
                dcz=((dcz-rev*x)%n+n-1)%n+1;
                break;
            
            case F:
                rev*=-1;
                break;
            
            case S:
                scanf("%d%d",&x,&y);
                x=((dcz+rev*x-rev)%n+n-1)%n+1;y=((dcz+rev*y-rev)%n+n-1)%n+1;
                Query(rt,1,n,x,x);Query(rt,1,n,y,y);
                int a=t[rv[x]].l,b=t[rv[y]].l;
                Color(rt,1,n,x,x,b);Color(rt,1,n,y,y,a);
                break;
            
            case P:
                scanf("%d%d%d",&x,&y,&z);
                x=((dcz+rev*x-rev)%n+n-1)%n+1;y=((dcz+rev*y-rev)%n+n-1)%n+1;
                if (rev<0) swap(x,y);
                if (x<=y) Color(rt,1,n,x,y,z);
                else Color(rt,1,n,x,n,z),Color(rt,1,n,1,y,z);
                break;
            
            case C:
                x=1,y=n;
                if (ord[1]==S) scanf("%d%d",&x,&y),x=((dcz+rev*x-rev)%n+n-1)%n+1,y=((dcz+rev*y-rev)%n+n-1)%n+1;
                 if (rev<0&&ord[1]==S) swap(x,y);
                if (ord[1]!=S) 
                    int z=Query(rt,1,n,1,n);    
                    printf("%d\n",z=z-((z!=1)?(t[rt].l==t[rt].r):0));
                
                else
                if (x<=y) printf("%d\n",z=Query(rt,1,n,x,y));
                else 
                    int z=Query(rt,1,n,x,n)+Query(rt,1,n,1,y);
                    printf("%d\n",z=z-((z!=1)?(t[rt].l==t[rt].r):0));
                
            
        
    
View Code

 

以上是关于[线段树]JZOJ 1214 项链工厂的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1493[NOI2007]项链工厂 线段树

BZOJ1493 NOI2007 项链工厂 线段树模拟

1493: [NOI2007]项链工厂

Bzoj1493--Noi2007项链工厂

JZOJ4605. 排序(线段树合并与分裂)

SDOI2009HH的项链 线段树