W
e
l
c
o
m
e
: )

[Ynoi2014] 人人本着正义之名

题传

考虑 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;
}
posted @ 2023-02-14 15:57  127_127_127  阅读(23)  评论(0编辑  收藏  举报