题传

考虑 3/4/5/6 操作,发现本质上是对某段颜色相同的段向左/右拓展。

考虑 1/2 为区间推平操作,其它操作只会减少颜色段,因此总颜色段为 \(O(n+m)\) 的,直接平衡树维护即可。

然而巨巨巨巨难写》

Code:

#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <cctype>
#include <vector>
#include <queue>
#include <bitset>
#include <iostream>
#define vi vector<int>
#define pb push_back
#define mp make_pair
#define st first
#define nd second
using namespace std;
typedef long long ll;
typedef pair <int, int> Pii;
const int INF=0x3f3f3f3f;
const int cp=998244353;
inline int mod(int x){if(x>=cp) x-=cp;if(x<0) x+=cp;return x;}
inline void plust(int &x, int y){x=mod(x+y);return ;}
inline void minut(int &x, int y){x=mod(x-y);return ;}
inline int read(){
char ch=getchar();int x=0, f=1;
while(!isdigit(ch)){if(ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
inline void write(int x){
if(x<0) putchar('-'), x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
inline int ksm(int a, int b=cp-2){
int ret=1;
for(; b; b>>=1, a=1ll*a*a%cp)
if(b&1) ret=1ll*ret*a%cp;
return ret;
}
const int N=3e6+6;
const int M=1e7;
typedef unsigned int ui;
ui seed=20061207;
inline ui rnd(){seed^=seed<<7;seed^=seed>>11;seed^=seed<<13;return seed;}
namespace FHQ{
inline int mn(int a, int b){return (a<b)?a:b;}
struct node{
ui key;int col, sum, siz[2], l, r, tagl, tagr, mnl[2];node *ls, *rs;
//自己的颜色 子树和 子树0/1区间个数 自己的区间 子树 1 端点偏移量 子树0/1最短段长
void up(){siz[col]=1, siz[!col]=0;sum=col*(r-l+1);tagl=tagr=0, mnl[col]=r-l+1, mnl[!col]=INF;}
node(){}node(ui ky, int c, int lp, int rp){key=ky, col=c, l=lp, r=rp, sum=0, ls=NULL, rs=NULL;up();}
void tag(int tl, int tr){
tagl+=tl, tagr+=tr;mnl[0]-=tl+tr, mnl[1]+=tl+tr;sum+=(tl+tr)*siz[1];
if(col) l-=tl, r+=tr;else l+=tr, r-=tl;
}
void print(){printf("%d %d %d %d %d\n", col, sum, l, r, key);}
void pushdown(){
if(tagl||tagr){
if(ls!=NULL) ls->tag(tagl, tagr);
if(rs!=NULL) rs->tag(tagl, tagr);
}tagl=tagr=0;
}
node operator + (const node &R) const{
node res=*this;res.sum+=R.sum;res.siz[0]+=R.siz[0];res.siz[1]+=R.siz[1];
res.mnl[0]=min(res.mnl[0], R.mnl[0]);res.mnl[1]=mn(res.mnl[1], R.mnl[1]);
return res;
}
void pushup(){up();if(ls!=NULL) *this=*this+*(this->ls);if(rs!=NULL) *this=*this+*(this->rs);}
}fhq[M];int ndc;node *root;
inline node* clr(int c, int l, int r){return &(fhq[++ndc]=node(rnd(), c, l, r));}
void splitL(node *k, int v, node *&x, node *&y){
if(k==NULL) return (void)(x=y=NULL);k->pushdown();
if(k->l<=v) x=k, splitL(k->rs, v, x->rs, y);
else y=k, splitL(k->ls, v, x, y->ls);k->pushup();
}
void splitR(node *k, int v, node *&x, node *&y){
if(k==NULL) return (void)(x=y=NULL);k->pushdown();
if(k->r<=v) x=k, splitR(k->rs, v, x->rs, y);
else y=k, splitR(k->ls, v, x, y->ls);k->pushup();
}
node* merge(node *x, node *y){
if(x==NULL) return y;if(y==NULL) return x;
x->pushdown(), y->pushdown();
if(x->key<y->key) return x->rs=merge(x->rs, y), x->pushup(), x;
else return y->ls=merge(x, y->ls), y->pushup(), y;
}
vector<node*> tmp;
void dfs(node *k){
if(k==NULL) return ;if(k->mnl[0]&&k->mnl[1]) return ;k->pushdown();
if(k->l>k->r) tmp.pb(k);dfs(k->ls);dfs(k->rs);
}
inline void maintain(){
vector<node*> ().swap(tmp);dfs(root);
for(int i=0; i<tmp.size(); ++i){
// printf(">>%d\n", i);
node *x=tmp[i], *L=NULL, *M=NULL, *R=NULL, *y=NULL;
splitL(root, x->l-1, root, R);splitL(R, x->l, y, R);splitR(root, x->l-2, root, L);
if(x==y) M=(x->ls==NULL)?x->rs:x->ls;else M=y, M->ls=M->rs=NULL;
if(L!=NULL&&M!=NULL) L->r=M->r, L->up(), M=NULL;
root=merge(merge(merge(root, L), M), R);
}
}
inline void insert(int c, int l, int r){node *p=clr(c, l, r);root=merge(root, p);}
void print(node *k=root){
if(k==NULL) return ;k->pushdown();
printf("[%d %d] col %d %d\n", k->l, k->r, k->col, k->sum);
cout<<k<<" ls="<<k->ls<<" rs="<<k->rs<<endl;
print(k->ls);print(k->rs);
}
inline void mdy(int l, int r, int c){
node *L=NULL, *M=NULL, *R=NULL, *x=NULL;//print();
splitR(root, l-1, root, x);splitL(x, r, x, R);
splitL(x, l-1, L, x);splitR(x, r, x, M);
if(L!=NULL){if(L->r>r) M=clr(L->col, r, L->r);L->r=l-1;L->up();}
else splitR(root, l-2, root, L);
if(M!=NULL) M->l=r+1, M->up();
else splitL(R, r+1, M, R);
x=clr(c, l, r);if(L!=NULL&&L->col==c) x->l=L->l, x->up(), L=NULL;
if(M!=NULL&&c==M->col) x->r=M->r, x->up(), M=NULL;
root=merge(merge(merge(merge(root, L), x), M), R);
}
inline void nxt_mdy(int l, int r, int tl, int tr){
node *x=NULL, *y=NULL, *R=NULL;
splitR(root, l-1, root, y);splitL(y, r, y, R);splitL(y, l, x, y);
if(x!=NULL&&x->col==tl) root=merge(root, x);
else y=merge(x, y);x=NULL;splitR(y, r-1, y, x);
if(x!=NULL&&x->col==abs(tr)){
if(x->r>r) R=merge(x, R);
else{
y=merge(y, x);node *M=NULL;
splitL(R, r+1, M, R);y=merge(y, M);
}
}
else y=merge(y, x);if(y!=NULL) y->tag(tl, tr);
root=merge(merge(root, y), R);maintain();
}
void lst_mdy(int l, int r, int tl, int tr) {
node *x=NULL, *y=NULL, *R=NULL;
splitR(root, l-1, root, y);splitL(y, r, y, R);splitL(y, l, x, y);
if(x!=NULL&&x->col==abs(tl)) {
if(x->l<l) root=merge(root, x);
else{
y=merge(x, y);node *M=NULL;
splitR(root, l-2, root, M);y=merge(M, y);
}
}
else y=merge(x, y);x=NULL;
splitR(y, r-1, y, x);
if(x!=NULL&&x->col==tr) R=merge(x, R);
else y=merge(y, x);
if(y!=NULL) y->tag(tl, tr);
root=merge(merge(root, y), R);maintain();
}
inline int qry(int l, int r){
node *p=NULL, *q=NULL, *R=NULL;int res=0;
splitR(root, l-1, root, p);splitL(p, r, p, R);
if(p!=NULL) res+=p->sum;splitL(p, l-1, q, p);
if(q!=NULL) res-=q->col*(l-q->l);p=merge(q, p);q=NULL;
splitR(p, r, p, q);if(q!=NULL) res-=q->col*(q->r-r);
root=merge(merge(root, merge(p, q)), R);return res;
return res;
}
}
int n, m;bool a[N];
signed main(){
n=read(), m=read();
for(int i=1, j=1; i<=n; ++i){
char ch=getchar();while(!isdigit(ch)) ch=getchar();
// printf("-----%c\n", ch);
a[i]=ch-'0';if(i>1&&a[i]!=a[i-1]) FHQ :: insert(a[i-1], j, i-1), j=i;
if(i==n) FHQ :: insert(a[n], j, i);
}
for(int i=1, ans=0; i<=m; ++i){
int op=read(), l=read()^ans, r=read()^ans;
if(l>r) swap(l, r);
if(op<=2) FHQ :: mdy(l, r, op-1);
else if(op==7) printf("%d\n", ans=FHQ :: qry(l, r));
else if(op&1) FHQ :: nxt_mdy(l, r-1, op==3?1:0, op==3?0:-1);
else FHQ :: lst_mdy(l+1, r, op==4?0:-1, op==4?1:0);
// FHQ :: print();puts("");
}
return 0;
}

[Ynoi2014] 人人本着正义之名的更多相关文章

  1. [Ynoi2014]不归之人与望眼欲穿的人们

    题目大意: 给定一个序列,每次单点修改一个数,或给定$x$,询问最短的or起来大于等于$x$的区间的长度(不存在输出-1). 解题思路: 在太阳西斜的这个世界里,置身天上之森.等这场战争结束之后,不归 ...

  2. [Ynoi2015]即便看不到未来

    题目大意: 给定一个序列,每次询问,给出一个区间$[l,r]$. 设将区间内的元素去重后重排的数组为$p$,求$p$中长度为$1\sim 10$的极长值域连续段个数. 长度为$L$的极长值域连续段的定 ...

  3. [Ynoi2015]纵使日薄西山

    题目大意: 给定一个序列,每次单点修改,然后进行询问. 定义一次操作为,选择一个位置$x$,将这个位置的数和左边.右边两个位置的数(不存在则忽略)各减去1,然后和0取max. 对序列中最大的位置进行一 ...

  4. [Ynoi2015]盼君勿忘

    题目大意: 给定一个序列,每次查询一个区间\([l,r]\)中所有子序列分别去重后的和\(\bmod p\)(每次询问模数不同). 解题思路: 在太阳西斜的这个世界里,置身天上之森.等这场战争结束之后 ...

  5. [Ynoi2015]我回来了

    题目大意: 给定一张无向无权图,每次给定若干个二元组\((x_i,y_i)\),定义点\(u\)满足条件,当且仅当存在\(i\),并满足\(dist(u,x_i)\leqslant y_i\)(\(d ...

  6. [Ynoi2015]此时此刻的光辉

    题目大意: 给定一个序列,每次询问一段区间的数的乘积的约数个数. 解题思路: 在太阳西斜的这个世界里,置身天上之森.等这场战争结束之后,不归之人与望眼欲穿的众人, 人人本着正义之名,长存不灭的过去.逐 ...

  7. 题解 P5072 【[Ynoi2015] 盼君勿忘】

    在太阳西斜的这个世界里,置身天上之森.等这场战争结束之后,不归之人与望眼欲穿的众人, 人人本着正义之名,长存不灭的过去.逐渐消逝的未来.我回来了,纵使日薄西山,即便看不到未来,此时此刻的光辉,盼君勿忘 ...

  8. Do you have an English name? 你有英文名吗?

    文中提到的所有人名都是虚构的,如有雷同,纯属巧合. 当然,你的洋名儿也可能是德文.法文.意大利文,等々々々. 全球化时代,和老外的交流也多了."高端"的程序员想要进欧美系外企,想要 ...

  9. 自学JQuery Mobile的几个例子

    JQuery Mobile是一个用于构建移动Web应用程序的框架,适用于主流的移动设备(智能手机.平板电脑),该框架利用了HTML5和CSS3技术减少了额外的脚本文件的编写.具体JQuery Mobi ...

  10. The fifth day

    All men cannot be first . 今日单词: first(形容词):第一的:基本的:最早的:(副词):第一:首先 翻译:不可能人人都是第一名. <Only Love>-- ...

随机推荐

  1. 【SpringCloud】SpringCloud config分布式配置中心

    SpringCloud config分布式配置中心 概述 分布式系统面临的---配置问题 微服务意味着要将单体应用中的业务拆分成一个个子服务 ,每个服务的粒度相对较小,因此系统中会出现大量的服务.由于 ...

  2. 《机器人SLAM导航核心技术与实战》第1季:第0章_SLAM发展综述

    <机器人SLAM导航核心技术与实战>第1季:第0章_SLAM发展综述 视频讲解 [第1季]0.第0章_SLAM发展综述-视频讲解 [第1季]0.1.第0章_SLAM发展综述-梳理定位导航技 ...

  3. c数组与结构体

    数组,存储同类型的复合类型:结构体,存储不同类型的复合类型,用于自定义数据结构. 计算机中,针对存储大量数据的集合,有着两种方式,一种是以块式集中存储数据,这就是数组的存储方式,大量同类型的数据集中放 ...

  4. Kylin-Server-V10-SP3物理机安装简要过程

    1.下载镜像 链接: https://eco.kylinos.cn/partners/mirror.html?class_id=1&query_key=V10 选择: 银河麒麟高级服务器操作系 ...

  5. Unity/Auto Layout -- 理解Layout Elements(布局元素)

  6. Git撤销本地commit(未push)

    查询commit日志 git log 查询到自己commit的上个版本id(commit_id) 撤销(这里是放弃自己commit的更改,直接回退到上个版本源码) git reset --hard c ...

  7. MySQL 中的 MVCC 是什么?

    MySQL 中的 MVCC 是什么? MVCC(Multi-Version Concurrency Control) 是 MySQL 数据库用来处理并发访问的技术,特别是在 InnoDB 存储引擎中, ...

  8. 一文速通Python并行计算:08 Python多进程编程-multiprocessing模块、进程的创建命名、获取进程ID、创建守护进程和进程的终止

    一文速通 Python 并行计算:08 Python 多进程编程-multiprocessing 模块.进程的创建命名.获取进程 ID.创建守护进程和进程的终止 摘要: 本节介绍 Python 中 m ...

  9. Sentinel——热点规则

    目录 热点规则 配置热点规则 API配置热点规则 热点规则 热点规则是用于实现热点参数限流的规则.热点参数限流指的是,在流控规则中指定对某方法参数的 QPS 限流后,当所有对该资源的请求URL中携带有 ...

  10. 【安装】Ubuntu 20.04下快速安装ROS2 Foxy

    参考博客 ROS2安装 有的地方原博主打错了,还没改过来,我按我自己的改好了. 有的地方比如github和raw.githubusercontent.com访问不了,我替换成能用的镜像源了,只求一键复 ...