题传

考虑 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. Try .NET & Github Gist

    Try .NET Try .NET 是微软最近推出的在线 C# 运行环境,不用安装 Visual Studio 等,就可以直接上手写 C# 代码. 可以先进来写两行代码看看 https://try.d ...

  2. Web前端入门第 23 问:CSS 选择器的优先级

    任何地方都存在阶级,CSS 选择器也不例外,也会讲一个三六九等. 选择器类别 通配符选择器 标签选择器 类选择器 ID选择器 属性选择器 伪类选择器 伪元素选择器 关系选择器 流传已久的阶级划分 选择 ...

  3. 康谋分享 | aiSim5 物理相机传感器模型验证方法(一)

    摘要: aiSim5可以实时模拟复杂的传感器配置,在多GPU分布式渲支持的支持下,aiSim可以渲染20多个摄像头.10多个雷达和10多个激光雷达在同一环境下运行.aiSim5独有的实时渲染引擎能够满 ...

  4. macOS 软件推荐

    五星推荐: ezip 解压压缩文件  https://ezip.awehunt.com/ (免费) microsoft To Do : https://todo.microsoft.com/tasks ...

  5. liunx git 免密码登录

    vscode远程git或在linux环境使用git时,每次clone都要输入帐号密码,很不方便,可以使用下面一行命令,系统会记录你输入的下一次帐号密码.(明文记录,注意规避风险)   # 执行   g ...

  6. 查询相册更加mysql 查询

    接到一个项目项目案例相册是这种结构 大佬建议 sql 查询 groip 进行时间统计今天 field根据mysql 时间查询进行统计 今天多少条 新增多少条相册 计算天数 $lists = Album ...

  7. 通过Linux包管理器提升权限

    免责声明:本文所涉及的技术仅供学习和参考,严禁使用本文内容从事违法行为和未授权行为,如因个人原因造成不良后果,均由使用者本人负责,作者及本博客不承担任何责任. 前言 在Linux系统中,apt和yum ...

  8. NOIP集训 P4137 Rmq Problem / mex 题解

    前置指使:可持久化线段树 题解:P4137 Rmq Problem / mex 有一个长度为 \(n\) 的数组 \(\{ a_1,a_2,...,a_n \}\) . \(m\) 次询问,每次询问一 ...

  9. Java编程--String类和基本数据类型的相互转换

    基本数据类型:byte.short.int.long.char.float.double.boolean 基本数据类型->String:利用String类提供的ValueOf(基本类型)方法转换 ...

  10. 【记录】Python3|用百度语音 API 朗读你的小说TXT

    百度语音合成官方教程_AI开放平台 百度语音合成官方demo_github.com 简单地写了一个按段落朗读文本的demo:DEMO链接_gitee.com. 有时候会请求不到数据,不知道是网络原因还 ...