[线段树]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 31 2 3 2 14CR 2P 5 5 2CS 4 1

Sample Output

41

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));
                }
            }
        }
    }
}

原文地址:https://www.cnblogs.com/mastervan/p/11145014.html

时间: 2024-08-01 09:55:17

[线段树]JZOJ 1214 项链工厂的相关文章

[线段树]JZOJ 5812

Description 每一个机房中总有一个红太阳.有一天,AmberFrame 来到机房,发现桌上有不知道哪个蒟蒻放上的问 题: 有一个 n 个数的序列,一开始所有的数都是 0,每次可以将一个区间 [l, r](l ≤ r) 内的数 +1,求到达最 终状态的最少操作次数. AmberFrame 非常强,自然不会把时间花在这种水题上.因此他就把任务交给了你,如果不会做的话,他 可能就会觉得你就是那个放问题的蒟蒻了而把你批判一番了. Input 第一行包含一个正整数 n,表示序列的长度.第二行包含

[线段树] Jzoj P4231 寻找神格

Description 淬炼完神体,王仙女被传送到了遥远处一座没有神雷的浮岛上,发现浮岛上除了一扇门以外什么都没有.他来到门前,发现上面写着这样一段话:一个神出了拥有强大的神体外,还需要一枚神格.然而,想要获得神格没那么简单,除了有实力外还需要有运气.曾经有一个人叫金(jin)字(zi)塔(da),他的神体很强,很壮,可是他根本没有运气,所以最后神格拒绝了他.打开这扇门,你将会进入一个神格创造的空间,在那里,神格将会问你一些问题来测试你解决问题的能力,当然,它的问题将会很难,在你答不出来的时候你

[扫描线][线段树]JZOJ 4238 纪念碑

Description 2034年,纪念中学决定修建校庆100周年纪念碑,作为杰出校友的你被找了过来,帮校方确定纪念碑的选址.纪念中学的土地可以看作是一个长为n,宽为m的矩形.它由n* m个1*1的正方形组成,其中左下角的正方形的坐标为(1,1),右上角的正方形的坐标为(n, m).其中有一些土地已经被用来修建建筑物,每一幢建筑物都可以看做是一个左下角为(x1,y1),右上角为(x2,y2)的矩形.纪念碑可以看作是一个正方形.校方希望你找出一块最大的正方形区域供他们参考. Input 每一组数据

[扫描线][倍增][dfs序][线段树] Jzoj P6276 树

Description 有一棵n个节点的无根树,给出其中的m对点对<x,y>.问有多少条树上的简单路径<u,v>满足该路径上不存在任何一对给出的点对<x,y>. 这里我们认为路径<u,v>和<v,u>是相同的.并且对于题目中给出的点对<x,y>满足x!=y,对于你要计数的路径<u,v>满足u!=v(即单点不算答案). 题解 我们先把每个点在dfs上入队出队的时间给弄出来 然后可以转换为在平面上的n个矩阵 就可以用扫描线+线

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 行每行一

bzoj1493[NOI2007]项链工厂 线段树

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

BZOJ1493 NOI2007 项链工厂 线段树模拟

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

【SDOI2009】HH的项链 线段树

题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH 不断地收集新的贝壳,因此,他的项链变得越来越长.有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答……因为项链实在是太长了.于是,他只好求助睿智的你,来解决这个问题. 输入输出格式 输入格式: 第一行:一个整数N,表示项链的长度. 第二行:N 个整数,表示依次表示项链中贝壳的编号(编号为0 到1000000 之间

[SDOI2009]HH的项链-树状数组/线段树

树状数组: 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn = 1000010; 4 int id[maxn],tree[maxn],vis[maxn],num[maxn]; 5 int n,m; 6 struct Tree{ 7 int l,r; 8 int pos; 9 }; 10 Tree a[maxn]; 11 int buf[17]; 12 inline void read(int &x){