题解:P11146 「SFMOI Round I」Strange Train Game

Link\text{Link}

题意

题目本身已经够简洁了,故直接搬来。

给定长度为 nn0101a,ba,b,给定 2m2m 个正整数 li,ril_i,r_i。对于 i=1,2,,mi=1,2,\cdots,m依次执行以下操作:

  • 选择是否执行第 ii 次操作。
    • 如果执行,则对于 k=li,li+1,,rik=l_i,l_{i}+1,\cdots,r_i,交换 ak,bka_k,b_k

最大化 aa 的字典序并输出最终的结果。

分析

显然,a,ba,b 相同的位怎么操作都不变,可以直接丢掉。

剔除后每个操作相当于给 aa 的一个区间异或上 11,我们只要贪心地让高位取最大就行了。

考虑部分分的情况:所有的 lil_i 互不相同,显然每个操作对第 lil_i 位的影响是唯一的,根据 aa 贪心地选即可。

若存在 lil_i 相同,不妨考虑最简单的情况(有被异或到的用 11 表示,否则用 00 表示):

11100
11111

这两个操作选或不选构成的 44 种情况分别是:

00000
11100
00011
11111

和操作 1110000011 构成的结果相同!也就是说我们把 11111 改成 00011 并不影响答案!根据归纳法,这个东西可以扩展到多个的情况,如 44 个:

110000 <=> 110000
111000 <=> 001000
111110 <=> 000110
111111 <=> 000001

于是我们就能把 lil_i 相同的情况转化为 lil_i 不同的,若两个操作会变成完全一样则可以去掉一个。这道题就做完了。

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
long long read(){
	long long x=0,f=1;char ch=getchar();
	while(!isdigit(ch))
	{if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
void write(long long x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
const int N=2e5+10;
int n,m,tn,tm;
string sa,sb;
struct oper{
	int l,r;
}op[N];
int id[N],a[N],b[N];
int mu[N];
vector<int>adl[N];
bool cmp(int x,int y){
	return op[x].r<op[y].r;
}
int main(){
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	n=read();m=read();
	cin>>sa>>sb;
	for(int i=1;i<=m;i++){
		op[i].l=read();op[i].r=read();
	}
	for(int i=1;i<=n;i++){
		if(sa[i-1]!=sb[i-1]){
			a[++tn]=sa[i-1]-'0';
			b[tn]=sb[i-1]-'0';
			id[tn]=i;
		}
	}
	for(int i=1;i<=m;i++){
		if(op[i].l>id[tn]||op[i].r<id[1])continue;
		op[i].l=lower_bound(id+1,id+tn+1,op[i].l)-id;
		op[i].r=upper_bound(id+1,id+tn+1,op[i].r)-id-1;
		if(1<=op[i].l&&op[i].l<=op[i].r&&op[i].r<=tn){
			adl[op[i].l].push_back(i);
		}
	}
	int now=0,lst=0;
	for(int i=1;i<=tn;i++){
		now^=mu[i];
		if(adl[i].size()){
			sort(adl[i].begin(),adl[i].end(),cmp);
			int x=adl[i][0];
			for(int j=1;j<adl[i].size();j++){
				if(op[adl[i][j]].r==op[adl[i][j-1]].r)continue;
				adl[op[adl[i][j-1]].r+1].push_back(adl[i][j]);
			}
			adl[i].clear();adl[i].push_back(x);
			if(!(now^a[i])){
				mu[op[x].r+1]^=1;
				now^=1;
			}
			sa[id[i]-1]='1';
		}
		else{
			if(now^a[i])sa[id[i]-1]='1';
			else sa[id[i]-1]='0';;
		}
	}
	cout<<sa<<endl;
	return 0;
}
posted @ 2024-10-03 08:18  luckydrawbox  阅读(17)  评论(0)    收藏  举报  来源