D题:
思路:一开始我们会去选择字母a放在左边还是右边,然后会再去选择字母b放在左边或者右边,一直这样循环下去直到只剩下一个字母。那么每次面临的选择就是2次,总共会是2^k=n,则我们可以直接用深搜去解决这道题,并且先用前缀和去预处理出每个区间的每个字母的数量。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
typedef long long ll;
const int MAXN=1e6+5;
const int M=1e6+5;
const double eps=1e-7;
const ll INF=0x3f3f3f3f;
char s[MAXN];
int sum[30][MAXN];
int ans;
void dfs(int l,int r,char c,int cnt)
{
if(l==r)
{
if(s[l]==c) ans=min(ans,cnt);
else ans=min(ans,cnt+1);
return;
}
dfs(l,(l+r)/2,c+1,cnt+r-(l+r)/2-sum[c-'a'+1][r]+sum[c-'a'+1][(l+r)/2]);
dfs((l+r)/2+1,r,c+1,cnt+(l+r)/2-l+1-sum[c-'a'+1][(l+r)/2]+sum[c-'a'+1][l-1]);
}
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
cin>>s+1;
for(int i=1;i<=26;i++)
{
sum[i][0]=0;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=26;j++)
{
sum[j][i]=sum[j][i-1];
}
int k=s[i]-'a'+1;
sum[k][i]++;
}
ans=1e9;
dfs(1,n,'a',0);
cout<<ans<<endl;
}
}
E题:
思路:一开始先将这些边都存起来,在输入边的时候,若为有向边,则直接将边加入到图中,并且记录每个点的入度。然后我们可以用队列优化的拓扑去求出拓扑序,若在求拓扑的过程中发现环,则输出NO。为什么要求拓扑序呢?因为入度大的点的拓扑序越大,我们的策略是将那些无向边指向两个点中入度大的点,这样就可以保证不会形成环。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
typedef long long ll;
const int MAXN=2e5+5;
const double eps=1e-7;
const ll INF=0x3f3f3f3f;
int n,m;
int cnt=0;
int head[MAXN];
int pos[MAXN];
int in[MAXN];
struct EDGE
{
int to;
int next;
}e[MAXN];
struct node
{
int a,b;
int val;
}f[MAXN];
void add(int u,int v)
{
e[cnt].to=v;
e[cnt].next=head[u];
head[u]=cnt++;
}
int toposort()
{
queue<int>q;
int res=n;
int tot=0;
for(int i=1;i<=n;i++)
{
if(in[i]==0) {
q.push(i);res--;pos[i]=++tot;}
}
while(!q.empty())
{
int u=q.front();
q.pop();
in[u]--;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
in[v]--;
if(in[v]==0) {
q.push(v);res--;pos[v]=++tot;}
}
}
if(res==0) return 1;
else return -1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
head[i]=-1;
pos[i]=0;
in[i]=0;
}
cnt=0;
int u,v,w;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&f[i].val,&f[i].a,&f[i].b);
if(f[i].val==1) {
add(f[i].a,f[i].b);in[f[i].b]++;}
}
int kk=toposort();
if(kk==-1)
{
printf("NO\n");
}
else
{
printf("YES\n");
for(int i=1;i<=m;i++)
{
if(f[i].val==1) printf("%d %d\n",f[i].a,f[i].b);
else
{
if(pos[f[i].a]<pos[f[i].b]) printf("%d %d\n",f[i].a,f[i].b);
else printf("%d %d\n",f[i].b,f[i].a);
}
}
}
}
}