求助:为什么我的贪心做法是假的
查看原帖
求助:为什么我的贪心做法是假的
930037
YangRuibin楼主2024/10/18 21:53

我的思路是,对于一个左边的字符,匹配最右边的未选过的不一样的字符;对于一个右边的字符,匹配最左边的未选过的不一样的字符。剩下没选的如果下标在某一对中间,就插入到这一对中。然而交了之后发现得到的 kk 的值并非最大的。

我想知道这种做法为什么假了。

代码:

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,tt,presta,st[N],ed[N],tot;
char s[N];
bool v[N];
vector<int>g[N];
struct tree{
	int data[N*4];
	void add(int p,int l,int r,int x,int k)
	{
		if(l==r)
		{
			data[p]+=k;return;
		}
		int mid=l+r>>1;
		if(x<=mid)add(p<<1,l,mid,x,k);
		else add(p<<1|1,mid+1,r,x,k);
		data[p]=data[p<<1]+data[p<<1|1];
	}
	int askr(int p,int l,int r)
	{
		if(l==r)return l;
		int mid=l+r>>1;
		if(data[p<<1|1])return askr(p<<1|1,mid+1,r);
		else return askr(p<<1,l,mid);
	}
	int askl(int p,int l,int r)
	{
		if(l==r)return l;
		int mid=l+r>>1;
		if(data[p<<1])return askl(p<<1,l,mid);
		else return askl(p<<1|1,mid+1,r);
	}
}t[26];
struct pos{
	int data,lazy;
};
struct tree2{
	pos a[N*4];
	void pushdown(int &p)
	{
		if(!a[p].lazy)return;
		a[p<<1].data=a[p<<1|1].data=a[p].lazy;
		a[p<<1].lazy=a[p<<1|1].lazy=a[p].lazy;
		a[p].lazy=0;
	}
	void add(int p,int l,int r,int L,int R,int k)
	{
		if(L<=l&&r<=R)
		{
			a[p].data=a[p].lazy=k;return;
		}
		pushdown(p);
		int mid=l+r>>1;
		if(L<=mid)add(p<<1,l,mid,L,R,k);
		if(mid<R)add(p<<1|1,mid+1,r,L,R,k);
	}
	int ask(int p,int l,int r,int x)
	{
		if(l==r)return a[p].data;
		pushdown(p);
		int mid=l+r>>1;
		if(x<=mid)return ask(p<<1,l,mid,x);
		else return ask(p<<1|1,mid+1,r,x);
	}
}t2;
int precheck()
{
	int vis[26]={0};
	for(int i=1;i<=n;i++)vis[s[i]-'a']++;
	int ret=0,ret2=0;
	for(int i=0;i<26;i++)
	{
		if(vis[i])++ret;
		if(vis[i]>1)++ret2;
	}
	bool flag=1;
	for(int i=1;i<=n;i++)
		if(s[i]!=s[1])
		{
			flag=0;break;
		}
	if(flag)return 0;
	if(n%2==0)
	{
		if(ret==2&&ret2==1)return -1;
		return 1;
	}
	flag=1;
	for(int i=1;i<=n;i++)
		if(i!=(n+1)/2&&s[i]!=s[1])
		{
			flag=0;break;
		}
	if(flag)return 0;
	if(ret==2&&ret2==1)return -1;
	return 1;
}
int main()
{
	scanf("%d%d",&tt,&tt);
	while(tt--)
	{
		scanf("%d%s",&n,s+1);tot=0;
		presta=precheck();
		if(presta==0)
		{
			puts("Shuiniao");continue;
		}
		if(presta==-1)
		{
			puts("Huoyu");
			puts("1");
			printf("%d ",n);
			for(int i=1;i<=n;i++)printf("%d ",i);
			puts("");continue;
		}
		for(int i=0;i<26;i++)memset(t[i].data,0,sizeof(t[i].data));
		memset(t2.a,0,sizeof(t2.a));
		memset(v,0,sizeof(v));
		for(int i=1;i<=n;i++)
			for(int j=0;j<26;j++)
				if(j!=s[i]-'a')t[j].add(1,1,n,i,1);
		int l=1,r=n,lr=0;
		while(l<r)
		{
			while(l<r&&v[l])l++;
			while(l<r&&v[r])r--;
			if(l>=r)break;
			if(lr==0)
			{
				int ind=t[s[l]-'a'].askr(1,1,n);
				if(ind<=l)break;
				++tot;st[tot]=l;ed[tot]=ind;
				for(int j=0;j<26;j++)
				{
					if(j!=s[l]-'a')t[j].add(1,1,n,l,-1);
					if(j!=s[ind]-'a')t[j].add(1,1,n,ind,-1);
				}
				t2.add(1,1,n,l,ind,tot);
				v[l]=v[ind]=1;
			}
			else
			{
				int ind=t[s[r]-'a'].askl(1,1,n);
				if(ind>=r)break;
				++tot;st[tot]=ind;ed[tot]=r;
				for(int j=0;j<26;j++)
				{
					if(j!=s[r]-'a')t[j].add(1,1,n,r,-1);
					if(j!=s[ind]-'a')t[j].add(1,1,n,ind,-1);
				}
				t2.add(1,1,n,ind,r,tot);
				v[ind]=v[r]=1;
			}
			lr^=1;
		}
		for(int i=1;i<=tot;i++)g[i].clear();
		for(int i=1;i<=n;i++)
			if(!v[i])g[t2.ask(1,1,n,i)].push_back(i);
		printf("Huoyu\n%d\n",tot);
		for(int i=1;i<=tot;i++)
		{
			printf("%d %d ",g[i].size()+2,st[i]);
			sort(g[i].begin(),g[i].end());
			for(int x:g[i])printf("%d ",x);
			printf("%d\n",ed[i]);
		}
	}
	return 0;
}
2024/10/18 21:53
加载中...