E-Unforgivable Curse
思路
相距k或者k+1的点可以互换,仔细如果a 和 b可以互换,b和c可以互换那么,a和c也可以互换,那就想到可以用并查集来维护所有可以随意互换的连通块,用是否每个连通块都字母的情况都完全相同来判断。 但是这里有一个问题,每一个位置都要加进去 例如
5 3
abccc
baccc
可以 来实现,所以不管是不是相等都要维护
代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
const int N = 2e5+10;
int p[N];
map<int,int> cf;
int find(int x) // 并查集
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
int dt[N/10][26][2];
int main()
{
int t;
cin>>t;
while(t--)
{
int n,k;
cf.clear();
int l=0;
memset(dt,0,sizeof dt);
cin>>n>>k;
for(int i=0;i<=n;i++)p[i]=i;
string s,t;
cin>>s>>t;
t=" "+t,s=' '+s;
p[k+1]=1;
for(int i=k+2;i<=n;i++)
{
p[find(i)]=find(i-k);
p[find(i)]=find(i-k-1);
}
for(int i=1;i<=n;i++)
{
if(cf.find(find(i))==cf.end())cf[find(i)]=l++;
dt[cf[find(i)]][s[i]-'a'][0]++,dt[cf[find(i)]][t[i]-'a'][1]++;
}
//cout<<cf[2];
bool fl=true;
for(int i=0;i<l;i++)
{
for(int j=0;j<26;j++)if(dt[i][j][0]!=dt[i][j][1])fl=false;
}
if(fl)puts("YES");
else puts("NO");
}
}
然后就超时了
优化
仔细想想为什么是k和k+1,然后就会发现
1和k+1可以互换,也可以和k+2互换
2可以k+2,k+3可以互换,
我们会发现,是一个连通块
所以会有下面的结论
前提条件 s 和 t字母种类和数量完全一样,否则直接No
- 所有位置组成一个连通块,所以肯定可以可以
- 只要判断 是不是完全相等,因为,这个位置的字母不能互换,即不能动
- 所有位置都不能互换,直接判断是不是相等就行
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
const int N = 2e5+10;
int p[N];
int dt[26][2];
int main()
{
int tt;
ios::sync_with_stdio(false);
cin>>tt;
while(tt--)
{
int n,k;
bool fl=true;
memset(dt,0,sizeof dt);
cin>>n>>k;
for(int i=0;i<=n;i++)p[i]=i;
string s,t;
cin>>s>>t;
t=" "+t,s=' '+s;
for(int i=1;i<=n;i++)dt[t[i]-'a'][0]++,dt[s[i]-'a'][1]++;
for(int i=0;i<26;i++)if(dt[i][0]!=dt[i][1])fl=false;
if(!fl)
{
puts("NO");
continue;
}
if(n/2>=k)
{
puts("YES");
continue;
}
for(int i=max(0,n-k)+1;i<=k&&i<=n;i++)
{
if(s[i]!=t[i])fl=false;
}
if(fl)puts("YES");
else puts("NO");
}
}
F. Dasha and Nightmares
思路
- 字符串的数据这么大,而且最后答案也和字母种类有关,就可以尝试从26这个字母所有的种类入手
- 看每种字母的数量都要奇数,就可以考虑缩减字符串,例如字符串 ,就可以缩减成 即奇数留下,偶数去除,而这种字符刚好可以使用二进制来表示
- 因为最后要有25种字母,所以可以枚举缺少的字母
具体实现
可以使用 一个
例如 在缺少a的字符串中缩减为b的数量
因为所有字母种类的数量都要为奇数,且种类为25,所以就可以求出每一种字符串在最后缺少某种字母的唯一匹配
例如 b 在最后缺少a的唯一匹配为 cdef...xyz
代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
const int N = 1e6+10;
map<int,int>cf[27];
int st[N][27];
int mi[30];
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
int n,cgh=0;
mi[0]=1,mi[1]=2;
for(int i=2;i<28;i++)mi[i]=mi[i-1]*2;
for(int i=0;i<26;i++)cgh+=1<<i;
cgh=(~cgh);
long long sum=0;
cin>>n;
for(int i=0;i<n;i++)
{
string tem;
cin>>tem;
for(auto ch:tem)
{
st[i][ch-'a']++;
}
int a=0;
for(int j=0;j<26;j++)
{
if(st[i][j]&1)a+=1<<j;
}
for(int j=0;j<26;j++)if(st[i][j]==0)cf[j][a]++;
}
for(int tr=0;tr<26;tr++)
{
for(auto &i:cf[tr])
{
if(i.second==0)continue;
int cnt=((~i.first)^cgh)-mi[tr];
if(cf[tr].find(cnt)==cf[tr].end())continue;
sum+=1ll*(i.second)*cf[tr][cnt];
i.second=0,cf[tr][cnt]=0;
}
}
cout<<sum<<endl;
}
反思
根据这个题的调试过程得到的反思,关于map 和unordered_map的使用,可以不用看(未完成)