zoukankan      html  css  js  c++  java
  • [线段树]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
    ",z=z-((z!=1)?(t[rt].l==t[rt].r):0));
                    }
                    else
                    if (x<=y) printf("%d
    ",z=Query(rt,1,n,x,y));
                    else {
                        int z=Query(rt,1,n,x,n)+Query(rt,1,n,1,y);
                        printf("%d
    ",z=z-((z!=1)?(t[rt].l==t[rt].r):0));
                    }
                }
            }
        }
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    php之aop实践
    PHP一个类AOP的实现
    PHP系列学习之AOP
    PVE上安装黑裙辉6.2
    安装proxmox VE(PVE)教程
    x-forwarded-for的深度挖掘
    nginx的配置总结,有时间自己整理
    openresty入门文章(笔者自用)
    pve apt-get update error 升级报错-文章未完工和验证
    pve proxmox 常见问题,perl warning
  • 原文地址:https://www.cnblogs.com/mastervan/p/11145014.html
Copyright © 2011-2022 走看看