题传

考虑 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. 【SpringMVC】概述

    SpringMVC 概述 Spring 为展现层提供的基于 MVC 设计理念的优秀的 Web 框架,是目前最主流的 MVC 框架之一 Spring3.0 后全面超越 Struts2,成为最优秀的 MV ...

  2. Windows Server 2012 配置 FTP

    环境 Windows Server 2012 安装步骤 打开服务器管理器 管理 - 添加角色和功能 开始之前 选择安装类型 服务器选择 选择对应的服务器... 服务器角色 功能 确认 安装进度 配置步 ...

  3. DotNetGuide 突破了 8K + Star,努力打造C#/.NET/.NET Core全面的学习、工作、面试指南知识库!

    前言 转眼之间维护DotNetGuide(全面的C#/.NET/.NET Core学习.工作.面试指南知识库)已经持续超过了4年多的时间,Commit提交数也超过1400+,在前几天在 GitHub ...

  4. 邮件自动回复助手(Rasa/SMTP)实现教程

    在现代办公场景中,处理大量邮件是一项既耗时又容易出错的任务.为了提升工作效率,我们可以利用自然语言处理(NLP)和邮件传输协议(SMTP)技术,构建一个智能的邮件自动回复助手.本文将详细介绍如何使用P ...

  5. Windows系统优化 3-清理预安装软件

    事件起因: 经过我们上次 Windows系统优化 2-系统设置优化 之后,现在电脑已经基本上可以使用,不过对于有强迫症的我来说还差了一步,那就是系统预安装的软件: 对于我们刚入手的电脑你是否有 这些 ...

  6. 可视化图解算法:按之字形顺序打印二叉树( Z字形、锯齿形遍历)

    1. 题目 描述 给定一个二叉树,返回该二叉树的之字形层序遍历,(第一层从左向右,下一层从右向左,一直这样交替) 数据范围:0≤n≤1500,树上每个节点的val满足 |val| <= 1500 ...

  7. SQL 日常练习 (二十)

    也只是尽快搬完这快一个月 sql 的砖, 准备要来整新学习模块了, 因此, 正好趁着五一, 加波速. 也会一直坚守和追求, 学无止境, 气有浩然. 每次都会说, 这是一种精神的传承,而我想的是, 不仅 ...

  8. Ubuntu20.04 搭建Kubernetes 1.28版本集群

    环境依赖 以下操作,无特殊说明,所有节点都需要执行 安装 ssh 服务 安装 openssh-server sudo apt-get install openssh-server 修改配置文件 vim ...

  9. Bolt DIY架构揭秘:从模型初始化到响应生成的技术之旅

    Bolt DIY 是一个强大的开源AI辅助开发工具,允许用户在浏览器中进行全栈Web开发.它的核心特点是支持多种大型语言模型(LLM),包括OpenAI.Anthropic.Ollama.Google ...

  10. 网络编程:UDP connect连接

    UDP connect的作用 UDP connect函数的调用,并不会引起像TCP连接那样,和服务器目标端网络交互,并不会触发所谓的"握手"报文发送和应答. UDP套接字进行con ...