题解:「ROI 2017 Day 2」存储器

题目信息

题目链接

Luogu P10653LOJ 2770

题目描述

给定一个字符串 \(S\),设其长度为 \(n\),每个字符要么是 + 要么是 -

定义一个片段\(S\) 的一个子串 \(S[l,r]\) 满足下面三个条件:

  • \(l=1\) 或者 \(S_{l-1} \ne S_l\)
  • \(r=n\) 或者 \(S_{r+1} \ne S_r\)
  • \(S_l=S_{l+1}=\dots=S_{r-1}=S_r\)

定义一次变换为:

  • 选择 \(S\) 的两个相邻长度不同的片段,改变长度较小的那个片段的所有字符为其相反字符。(+ 变为 -- 变为 +

现在有 \(q\) 次询问,每次询问给出只包含 +- 并且长度相同的字符串 \(S_i,T_i\),请你判断 \(S_i\) 是否能够通过若干次变换得到 \(T_i\)

输入格式

第一行一个整数 \(q\) 表示询问次数。

接下来 \(q\) 行每行两个字符串 \(S_i,T_i\),含义如题所示。

输出格式

对于每次询问输出一行一个字符串 YesNo 表示是否可以完成题目所给要求。

样例输入 #1

3
++- +++
++-- ++++
++-+--+- ++++++++

样例输出 #1

Yes
No
Yes

样例输入 #2

3
++-+-- ++----
++-+-- +++---
-++- -++-

样例输出 #2

Yes
No
Yes

数据范围

注:本题只放部分数据,完整数据请左转 LOJ P2770 评测。

\(len=\sum |S_i|\)

子任务编号 分值 $1 \le len \le $ 特殊性质
\(1\) \(20\) \(16\) \(T_i\) 中没有 -
\(2\) \(30\) \(10^3\) \(T_i\) 中没有 -
\(3\) \(20\) \(10^6\) \(T_i\) 中没有 -
\(4\) \(20\) \(10^3\)
\(5\) \(10\) \(10^6\)

思路

很简单。

引理

\(S\) 分为一些片段后,每一个片段在 \(T\) 中都应该是相同的字符。例如在 \(S\) 中这个片段为 -----,则在 \(T\) 中应该对应 +++++-----

这个证明过程很简单。因为每一次修改都是将片段修改成片段,所以不存在片段不对应的情况。

做法

由上面的引理,可以知道其中一种判断 -1 的情况。

接着我们就知道需要被翻转的片段是哪些。对于一个片段,如果它能够被翻转,我们就会把这个片段翻转掉。假设从左往右中片段的长度分别为 \(llen,len,rlen\)。如果 \(llen+rlen>len\),那么这个片段一定会被合并变成 \(llen+len+rlen\)。此时与原序列的变化就是把左边和右边的变长了,于是就可能更新其它的需要被翻转的片段。如果到了最后仍然不能确定,那么就无解。

Code

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
//#define int long long
namespace gtx{
//	Fast IO
	void read(int &x){
		x = 0;int h = 1;char tmp;
		do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp));
		while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar();
		x*=h;
	}
	void read(char &x){do{x=getchar();}while(x==' '||x=='\n'||x=='\r');}
	void write(char x){putchar(x);}
	void write(int x){
		if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0;
		do{st[++tot]=x%10,x/=10;} while(x);
		while(tot){putchar(st[tot--]+'0');};
	}
	void write(int x,char y){write(x);write(y);}
	const int MAXN = 1e6+10;
	int n,tot;
	char a[MAXN],b[MAXN];
	struct block{
		int l,r,len,llen,rlen;
		bool use;
	}p[MAXN];
	int lst[MAXN],nxt[MAXN];
	bitset<MAXN> inque;
	queue<int> q;
	signed main(){
		scanf("%s%s",a+1,b+1);
		n = strlen(a+1);tot = 0;
		for(int i = 1;i<=n;i++){
			p[++tot].l = i;
			while(i<=n&&a[i]==a[p[tot].l]) i++;
			i--;
			p[tot].r = i;
			p[tot].len = p[tot].r-p[tot].l+1;
			p[tot].use = 0;
		}
		inque.reset();
		while(!q.empty()) q.pop();
		int sum = 0;
		p[tot+1].l = n;
		p[tot+1].r = n;
		p[tot+1].use = 0;
		nxt[tot+1] = tot+1;
		p[tot+1].len = 0;
		p[tot+1].llen = 0;
		p[tot+1].rlen = 0;
		p[0].l = 1;
		p[0].r = 1;
		p[0].use = 0;
		lst[0] = 0;
		p[0].len = 0;
		p[0].llen = 0;
		p[0].rlen = 0;
		for(int i = 1;i<=tot;i++) lst[i] = i-1;
		for(int i = 1;i<=tot;i++) nxt[i] = i+1;
		bool is_OK = 1;
		int psum = 0;
		for(int i = 1;i<=tot;i++){
			p[i].llen = p[i-1].len;
			p[i].rlen = p[i+1].len;
			for(int j = p[i].l;j<=p[i].r;j++) is_OK &= (b[j]==b[p[i].l]);
			if(a[p[i].l]!=b[p[i].l]) p[i].use = 1,psum++;
		}
		if(!is_OK) return puts("No"),0;
		for(int i = 1;i<=tot;i++){
			if(p[i].use&&max(p[i].llen,p[i].rlen)>p[i].len){
				q.push(i);
				sum++;
				inque.set(i);
			}
		}
		while(!q.empty()){
			int k = q.front();q.pop();
			p[lst[k]].r = p[nxt[k]].r;
			p[lst[k]].len = p[lst[k]].r-p[lst[k]].l+1;
			lst[nxt[nxt[k]]] = lst[k];
			nxt[lst[k]] = nxt[nxt[k]];
			p[lst[lst[k]]].rlen = p[lst[k]].len;
			p[nxt[nxt[k]]].llen = p[lst[k]].len;
			if(p[lst[lst[k]]].use&&max(p[lst[lst[k]]].llen,p[lst[lst[k]]].rlen)>p[lst[lst[k]]].len){
				if(!inque[lst[lst[k]]]){
					q.push(lst[lst[k]]);
					sum++;
					inque.set(lst[lst[k]]);
				}
			}
			if(p[nxt[nxt[k]]].use&&max(p[nxt[nxt[k]]].llen,p[nxt[nxt[k]]].rlen)>p[nxt[nxt[k]]].len){
				if(!inque[nxt[nxt[k]]]){
					q.push(nxt[nxt[k]]);
					sum++;
					inque.set(nxt[nxt[k]]);
				}
			}
			if(p[lst[k]].use||p[nxt[k]].use) return puts("No");
		}
		puts(sum==psum?"Yes":"No");
		return 0;
	}
}
signed main(){
	// freopen("store.in","r",stdin);
	// freopen("store.out","w",stdout);
//	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	int T = 1;
	gtx::read(T);
	while(T--) gtx::main();
	return 0;
}

tag

ROI
链表队列思维

posted @ 2024-08-19 17:28  GuTongXing  阅读(32)  评论(0)    收藏  举报