A B C都是水题。
C要讲一下
C 原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=6441
题解讲的很明白了:
A
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=1e5+10;
ll dp[N][4];
char s[N];
int main()
{
cin>>s+1;
int n=strlen(s+1);
for(int i=1;i<=n;++i)
{
if(s[i]=='a')
{
dp[i][1]=dp[i-1][1]+1;
dp[i][2]=dp[i-1][2];
dp[i][3]=dp[i-1][3];
}
else if(s[i]=='b')
{
dp[i][1]=dp[i-1][1];
dp[i][2]=dp[i-1][2]+dp[i-1][1];
dp[i][3]=dp[i-1][3];
//printf("i:%d %d\n",i,dp[i][2]);
}
else if(s[i]=='c')
{
dp[i][1]=dp[i-1][1];
dp[i][2]=dp[i-1][2];
dp[i][3]=dp[i-1][3]+dp[i-1][2];
}
else{
dp[i][1]=dp[i-1][1];
dp[i][2]=dp[i-1][2];
dp[i][3]=dp[i-1][3];
}
}
//rep(i,1,n) printf("%lld %lld %lld\n",dp[i][1],dp[i][2],dp[i][3]);
printf("%lld\n",dp[n][3]);
}
B
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const double eps=1.0e-5;
const int maxn=1000000+10;
const ll mod=1e9+7;
int m,n,t;
char a[maxn],b[maxn];
int nxt[maxn][30];
int main()
{
int n,t;
cin>>n>>t;
scanf("%s",a+1);
for(int i=n;i>=1;i--)
{
for(int j=0;j<=25;j++) nxt[i-1][j]=nxt[i][j];
nxt[i-1][a[i]-'a']=i;
}
while(t--)
{
scanf("%s",b+1);
m=strlen(b+1);
int flag=0;
bool flg=true;
for(int i=1;i<=m;i++)
{
flag=nxt[flag][b[i]-'a'];
if(flag==0){
puts("NO");
flg=false;
break;
}
}
if(flg) puts("YES");
//printf("III\n");
}
}
C 按照题解公式化简求答案即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
ll n;
cin>>n;
if(n==1||n==2)
{
printf("-1");
return 0;
}
ll b,c;
if(n%2==1)
{
b=(n*n-1)/2;
c=b+1;
}
else{
b=(n*n-4)/4;
c=b+2;
}
printf("%lld %lld",b,c);
}
D 题解说是二分图或最大流
但我是瞎搞过的。保存每个坐标被覆盖的区间,然后查询的枚举这些坐标的区间即可。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
const int N=1000;
struct node
{
int l,r;
bool operator<(const node&o)
{
return r<o.r;
}
}a[N];
int n,q;
vector<int>G[N];
bool vis[N];
int main()
{
cin>>n>>q;
rep(i,1,n) scanf("%d",&a[i].l);
rep(i,1,n) scanf("%d",&a[i].r);
sort(a+1,a+1+n);
//rep(i,1,n) printf("%d %d\n",a[i].l,a[i].r);
rep(i,1,n)
{
for(int j=a[i].l;j<=a[i].r;++j)
{
G[j].push_back(i);
}
}
while(q--)
{
int ql,qr;
scanf("%d%d",&ql,&qr);
int id=ql;
int ans=0;
rep(i,1,n) vis[i]=0;
while(id<=qr)
{
for(int i:G[id])
{
if(vis[i]) continue;
if(a[i].l<=id&&id<=a[i].r) {
ans++;
vis[i]=1;
break;
}
}
id++;
}
printf("%d\n",ans);
}
}
二分图做法:
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
struct node
{
int id,l,r;
}a[N];
int used[N],part[N];
vector<int>G[N];
bool find(int u)
{
for(int v:G[u])
{
//if(v<ql||v>qr) continue;
if(used[v]) continue;
used[v]=1;
if(part[v]==0||find(part[v]))
{
part[v]=u;
return 1;
}
}
return 0;
}
void solve(int ql,int qr)
{
int sum=0;
memset(part,0,sizeof(part));
for(int i=ql;i<=qr;++i)
{
memset(used,0,sizeof(used));
if(find(i)) sum++;
}
printf("%d\n",sum);
}
int main()
{
int n,q;
cin>>n>>q;
for(int i=1;i<=n;++i) cin>>a[i].l;
for(int i=1;i<=n;++i) cin>>a[i].r;
for(int i=1;i<=n;++i)
for(int j=a[i].l;j<=a[i].r;++j)
G[j].push_back(i);
while(q--)
{
int ql,qr;
scanf("%d%d",&ql,&qr);
solve(ql,qr);
}
}
E
其实就是构造一个数列是,1234123123.。。从1到4,或者是1到3.可以二分这个4,也可以二分分成了多少段。两者均可以通过公式转换一下。
那么题解有用的部分就是下面这一段:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,m;
bool cal(ll mi)
{
return (n/mi+1)*(n/mi+2)/2*(n%mi)+(n/mi)*(n/mi+1)/2*(mi-n%mi)<=m;
}
int main()
{
cin>>n>>m;
ll l=1,r=n;
ll ans=-1;
while(l<=r)
{
int mid=l+r>>1;
if(cal(mid))
{
ans=mid,r=mid-1;
}
else l=mid+1;
}
//printf("ans:%lld\n",ans);
for(int i=1;i<=n%ans;++i)
for(int j=1;j<=n/ans+1;++j) printf("%d ",j);
for(int i=1;i<=ans-n%ans;++i)
for(int j=1;j<=n/ans;++j) printf("%d ",j);
}