社区讨论

MnZn刚学OI,求卡常

P6578[Ynoi2019] 魔法少女网站参与者 3已保存回复 4

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
4 条
当前快照
1 份
快照标识符
@mico31nc
此快照首次捕获于
2025/11/24 12:48
3 个月前
此快照最后确认于
2025/11/24 15:08
3 个月前
查看原帖
https://www.luogu.com.cn/record/249265076
CPP
#include<bits/stdc++.h>
#pragma optimize("Ofast")
#pragma optimize("unroll-loops")
#pragma optimize("inline")
#pragma optimize("-ffast-math")
#pragma optimize("-falign-loops")
#pragma optimize("-funroll-loops")
#pragma optimize("-fstrict-aliasing")
using namespace std;
const int B=800;
inline int read(){
	int u=0;
	char c=getchar();
	while(c<'0'||c>'9') c=getchar();
	while(c>='0'&&c<='9'){
		u=(u<<3)+(u<<1)+(c^'0'); c=getchar();
	}
	return u;
}
inline void write(const long long &u){
	if(u<10) putchar(u^48);
	else write(u/10),putchar((u%10)^48);
}
struct opt{
	int tp,x,v,l,r;
};
opt w[B+5];
opt myopt[B+5];//备份修改操作
int a[300005],n,q;//维护原序列
int b[300005];//离散化后序列
int to[300005];//离散化对应
int h[300005];//每个数在哪个块中
//关键点的定义:对于修改,x为关键点;对于查询,l-1,r为关键点
struct block{//保证只有块尾可能是关键点
	int l,r;//对应原序列位置
	int c[B+5];//离散化后第一个>x的对应原序列位置(没有为r+1)
	int d[B+5];//离散化后最后一个>x的对应原序列位置(没有为l-1)
	int e[B+5];//离散化后除块尾最后一个>x的对应原序列位置(没有为l-1)
	int ans[B+5];//块内答案
};
block s[B*3+5];
int d[B*3+5],m;//m为块数
int x[B+5],k;//k为值域
int fir[B+5],fol[300005];//用于排序,会将值相同的数倒序插入qwq
int pre[300005],nxt[300005];//b中前一个严格大于b[i]的位置、后一个大于等于b[i]的位置
int tmp[300005],sz;//维护单调栈
//int ps[30005];
//long long ps2[300005];
void print(int id){
	cerr<<"这是第"<<id<<"块的信息:\n";
	cerr<<"对应原序列:["<<s[id].l<<","<<s[id].r<<"]\n";
	cerr<<"离散化值:";
	for(int i=s[id].l;i<=s[id].r;i++) cerr<<b[i]<<' '; cerr<<'\n';
	for(int i=1;i<=k;i++){
		cerr<<"c["<<i<<"]="<<s[id].c[i]<<"\td["<<i<<"]="<<s[id].d[i]<<"\t";
		cerr<<"e["<<i<<"]="<<s[id].e[i]<<"\tans["<<i<<"]="<<s[id].ans[i]<<"\n";
	}
	cerr<<'\n';
}
int tim1,tim2,tim3,tim4,tim21,tim22,tim221,tim222;
void solve(){
	const bool step1=1,step2=1,step3=1,step4=1;
//	step1: 离散化
	if(step1){
		clock_t st=clock();
		m=k=0;
		for(int i=1;i<=q;i++){
			if(w[i].tp==1) d[++m]=w[i].x;
			else{
				if(w[i].l!=1) d[++m]=w[i].l-1; d[++m]=w[i].r; x[++k]=w[i].x;
			}
		}
		x[++k]=n;
		sort(x+1,x+1+k); k=unique(x+1,x+1+k)-x-1;
		for(int i=1;i<=k;i++){
			for(int j=x[i];j>x[i-1];j--){
				to[j]=i;
			}
		}
		for(int i=n;i>0;i-=n/B) d[++m]=i;
		sort(d+1,d+m+1);
		m=unique(d+1,d+m+1)-d-1;
		for(int i=1;i<=m;i++) s[i].l=d[i-1]+1,s[i].r=d[i];
		for(int i=1;i<=m;i++){
			for(int j=s[i].l;j<=s[i].r;j++){
				h[j]=i;
			}
		}
		for(int i=1;i<=n;i++){
			b[i]=to[a[i]];
		}
		for(int i=1;i<=q;i++) if(w[i].tp==1) w[i].v=to[w[i].v]; else w[i].x=to[w[i].x];
		clock_t ed=clock();
		tim1+=ed-st;
	}
//	cerr<<"b序列:"; for(int i=1;i<=n;i++) cerr<<b[i]<<' '; cerr<<'\n';
//	cerr<<"step1: done.\n";
//	step2: 预处理块内信息
	if(step2){
		clock_t st=clock();
		sz=0;
		tmp[sz]=0; b[0]=0x3f3f3f3f;
		for(int i=1;i<=n;i++){
			while(b[tmp[sz]]<=b[i]) nxt[tmp[sz]]=i,sz--;
			pre[i]=tmp[sz]; tmp[++sz]=i;
		}
		for(int i=1;i<=sz;i++) nxt[tmp[i]]=n+1;
//		sz=0;
//		tmp[sz]=n+1; b[n+1]=0x3f3f3f3f;
//		for(int i=n;i>=1;i--){
//			while(b[tmp[sz]]<b[i]) sz--;
//			nxt[i]=tmp[sz]; tmp[++sz]=i;
//		}
		clock_t mid=clock();
		for(int i=1;i<=m;i++){
//			clock_t ss1=clock();
			/*
			for(int j=0;j<=k+1;j++) s[i].c[j]=s[i].r+1,s[i].e[j]=s[i].d[j]=s[i].l-1;
			for(int j=s[i].l;j<s[i].r;j++){
				if(s[i].c[b[j]-1]==s[i].r+1) s[i].c[b[j]-1]=j;
				s[i].d[b[j]-1]=j; s[i].e[b[j]-1]=j;
			}
			if(s[i].c[b[s[i].r]-1]==s[i].r+1) s[i].c[b[s[i].r]-1]=s[i].r;
			s[i].d[b[s[i].r]-1]=s[i].r;
			
			for(int j=k;j>=1;j--){
				if(s[i].c[j-1]>s[i].c[j]) s[i].c[j-1]=s[i].c[j];
				if(s[i].d[j-1]<s[i].d[j]) s[i].d[j-1]=s[i].d[j];
				if(s[i].e[j-1]<s[i].e[j]) s[i].e[j-1]=s[i].e[j];
			}
			*/
			int pos=0;
			for(int j=s[i].l;j<=s[i].r;j++){
				while(pos<b[j]) s[i].c[pos++]=j;
			}
			while(pos<=k+1) s[i].c[pos++]=s[i].r+1;
			pos=0;
			for(int j=s[i].r-1;j>=s[i].l;j--){
				while(pos<b[j]) s[i].e[pos++]=j;
			}
			while(pos<=k+1) s[i].e[pos++]=s[i].l-1;
//			pos=0;
//			for(int j=s[i].r;j>=s[i].l;j--){
//				while(pos<b[j]) s[i].d[pos++]=j;
//			}
//			while(pos<=k+1) s[i].d[pos++]=s[i].l-1;
			memcpy(s[i].d,s[i].e,k+2<<2);
			for(int j=b[s[i].r]-1;~j;j--){
				s[i].d[j]=s[i].r;
			}
//			clock_t ss2=clock();
			memset(fir,0,k+3<<2);
			for(int j=s[i].l;j<=s[i].r;j++){
				fol[j]=fir[b[j]]; fir[b[j]]=j;
			}
			memset(s[i].ans,0,k+3<<2);
			int nans=(s[i].r-s[i].l+1)*(s[i].r-s[i].l+2)/2;
			for(int j=k+1;j>1;j--){
				for(int c=fir[j];c;c=fol[c]){
					nans-=(min(nxt[c],s[i].r+1)-c)*(c-max(pre[c],s[i].l-1));
				}
				s[i].ans[j-1]=nans;
			}
//			clock_t ss3=clock();
//			tim221+=ss2-ss1; tim222+=ss3-ss2;
		}
		clock_t ed=clock();
		tim2+=ed-st;
		tim21+=mid-st; tim22+=ed-mid;
	}
//	for(int i=1;i<=m;i++) print(i);
//	cerr<<"step2: done.\n";
//	step3: 处理询问
    if(step3){
		clock_t st=clock();
		for(int i=1;i<=q;i++){
			if(w[i].tp==1){
				int x=w[i].x,v=w[i].v;
				int u=h[x];
				for(int j=k;j>=b[x];j--){
					s[u].ans[j]-=s[u].r-s[u].d[j];
				}
				memcpy(s[u].d,s[u].e,k+2<<2);
				for(int j=1;j<v;j++) s[u].d[j]=x;
				for(int j=k;j>=v;j--){
					s[u].ans[j]+=s[u].r-s[u].d[j];
				}
//				for(int j=v-1;s[u].c[j]==s[u].r+1;j--) s[u].c[j]=x;
//				for(int j=v;)
				if(v>b[x]){
					for(int j=1;j<v;j++){
						if(s[u].c[j]==s[u].r+1){
							s[u].c[j]=x;
						}
					}
				}else{
					for(int j=v;j<=k;j++){
						if(s[u].c[j]==x){
							s[u].c[j]=s[u].r+1;
						}
					}
				}

				b[x]=v;
//				cerr<<"1 "<<x<<" "<<v<<" done.\n";
//				print(u);
			}else{
				int l=h[w[i].l],r=h[w[i].r],x=w[i].x;
				int pos=w[i].l-1;//上一个大数的位置
				long long ans=0;
				for(int j=l;j<=r;j++){
                    ans+=s[j].ans[x];
					ans+=1ll*(s[j].c[x]-s[j].l)*(s[j].l-pos-1);
					if(s[j].d[x]!=s[j].l-1) pos=s[j].d[x];
				}
//				cerr<<"2 "<<w[i].l<<' '<<w[i].r<<' '<<w[i].x<<" done.\n";
				write(ans); putchar(10);
			}
		}
		clock_t ed=clock();
		tim3+=ed-st;
	}
//	cerr<<"step3: done.\n";
//	step4: 实际更新
	if(step4){
		clock_t st=clock();
		for(int i=1;i<=q;i++){
			if(myopt[i].tp==1){
				a[myopt[i].x]=myopt[i].v;
			}
		}
		clock_t ed=clock();
		tim4+=ed-st;
	}
//	cerr<<"step4: done.\n\n";
}
int main(){
//	for(int i=1;i<=30000;i++) ps[i]=i*(i+1)/2;
//	for(int i=1;i<=300000;i++) ps2[i]=1ll*i*(i+1)/2;
//	freopen("1.in","r",stdin); freopen("1.out","w",stdout);
	int m;
	n=read(); m=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
	}
	while(m--){
		q++; w[q].tp=read();
		if(w[q].tp==1) w[q].x=read(),w[q].v=read(),myopt[q]=w[q];
		else w[q].l=read(),w[q].r=read(),w[q].x=read(),myopt[q]={0,0,0,0,0};
		if(m%B==0){
			solve(); q=0;
		}
	}
	cerr<<"tim1: "<<tim1*1.0/CLOCKS_PER_SEC<<'\n';
	cerr<<"tim2: "<<tim2*1.0/CLOCKS_PER_SEC<<'\n';
	cerr<<"tim21: "<<tim21*1.0/CLOCKS_PER_SEC<<'\n';
	cerr<<"tim22: "<<tim22*1.0/CLOCKS_PER_SEC<<'\n';
//	cerr<<"tim221: "<<tim221*1.0/CLOCKS_PER_SEC<<'\n';
//	cerr<<"tim222: "<<tim222*1.0/CLOCKS_PER_SEC<<'\n';
	cerr<<"tim3: "<<tim3*1.0/CLOCKS_PER_SEC<<'\n';
	cerr<<"tim4: "<<tim4*1.0/CLOCKS_PER_SEC<<'\n';
	return 0;
}

回复

4 条回复,欢迎继续交流。

正在加载回复...