我靠!写的东西总被坑爹又不稳定的博客频道吞掉,我已经无力吐槽,也无力再写了!
简单写写题意题解。
A:
题意:给出n,m,a,b,表示坐n次公交,有单程票和多程票,多程票能用m次,单程票a元,多程票b元,求最少花费。
题解:动规, f[i]表示坐i次时最小花费,转移注意点就好了。不细说了,看代码,水水的!
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1005
using namespace std;
int f[N];
int n,m,a,b;
int main()
{
int i,j,k;
scanf("%d%d%d%d",&n,&m,&a,&b);
for(i=1;i<=n;i++)
{
f[i]=f[i-1]+a;
for(j=max(0,i-m);j<i;j++)
{
f[i]=min(f[i],f[j]+b);
}
}
printf("%d\n",f[n]);
return 0;
}
B:
题意:给出n,a,b,增加a或者b中至多一个的权值,使a*b>=6*n,输出a*b的最小值,及此时的a和b(SPJ)
题解:看代码吧,我毕竟被坑没A。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
long long n,a,b,c,d;
int main()
{
cin>>n>>a>>b;
n=n*6ll;
if(n<=a*b)
{
cout<<a*b;
printf("\n");
cout<<a<<' '<<b;
printf("\n");
return 0;
}
else
{
c=n/a;
if(a*c<n)c++;
d=n/b;
if(b*d<n)d++;
if(a*c<=b*d)
{
cout<<a*c;
printf("\n");
cout<<a<<' '<<c;
printf("\n");
return 0;
}
else
{
cout<<b*d;
printf("\n");
cout<<d<<' '<<b;
printf("\n");
return 0;
}
}
return 0;
}
C:
题意:给出n个数,把它们不打乱顺序分成三份(每份都不为空),使每份权值相同,问有多少种分法。
题解:正向反向预处理出权值前缀后缀和、之前之后有多少次权值正好为总权值1/3 。然后正着枚举,若前缀和是总权值1/3,看之后有多少种分法。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#define N 501000
using namespace std;
int n,a[N],ctl[N],ctr[N];
long long sum,suml[N],sumr[N];
long long ans;
int main()
{
int i,j,k;
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%d",&a[i]),sum+=a[i];
if(sum%3)
{
printf("0\n");
return 0;
}
sum/=3;
for(i=1;i<=n;i++)
{
suml[i]=suml[i-1]+a[i];
ctl[i]=ctl[i-1];
if(suml[i]==sum)ctl[i]++;
}
for(i=n;i;i--)
{
sumr[i]=sumr[i+1]+a[i];
ctr[i]=ctr[i+1];
if(sumr[i]==sum)ctr[i]++;
}
for(i=1;i<n-1;i++)
{
if(suml[i]==sum)ans+=ctr[i+2];
}
cout<<ans;
return 0;
}
D :
题意:给n个数,要把它们通过规定操作全变成m,问有多少种方案。
操作:把一个区间上每个数都权值+1,任意两次操作的左端点不能相同,任意两次操作的左端点不能相同,如[1,5],[2,5]和[1,4],[2,4]这两例都不合法。
题解: 没AC,也不会。
E:
题意:n个文员,m次操作。
操作一:输入 a,b , 表示a的上司设定为b
操作二:输入 a , 表示从a开始传递资料,a往其上司传,上司再往上一层传,一直到没上司为止。
操作三:输入 a,b , 表示询问文员a是否经手过资料b。
题解:(第四个点开始TLE)(觉得我的算法是O(n))
操作一为连边,b向a。
然后边有权值,为当前传过的资料号,
dfs时离线处理每次询问的答案,若传该资料的人到文员a的若干边的权值最大值大于资料号,则“NO”。小于则“YES”。
代码:可以去看我博客里的ygylca,里面有这种算法的思想(自创)。
#include <cstdio>
#include <algorithm>
#define N 1001000
using namespace std;
struct KSD
{
int v,len,next;
}e[N],eq[N];
int head[N],headq[N],cnt,cntq,dcount;
int crs[N],ans[N];
bool visit[N];
int n,m;
void add(int u,int v)
{
e[++cnt].v=v;
e[cnt].len=dcount;
e[cnt].next=head[u];
head[u]=cnt;
}
void addq(int u,int v,int len)
{
eq[++cntq].v=v;
eq[cntq].len=len;
eq[cntq].next=headq[u];
headq[u]=cntq;
}
int f[N],l[N];
inline int find(int x)
{
if(f[x]==x)return x;
int t=f[x];
f[x]=find(t);
l[x]=max(l[x],l[t]);
return f[x];
}
inline void dfs(int x,int p,int ll)
{
int i;
for(i=head[x];i;i=e[i].next)
{
dfs(e[i].v,x,e[i].len);
}
for(i=headq[x];i;i=eq[i].next)
{
if(find(eq[i].v)==x&&l[eq[i].v]<=eq[i].len)
{
ans[i]=1;
}
}
f[x]=p;
l[x]=ll;
}
int main()
{
// freopen("test.in","r",stdin);
// freopen("test.out","w",stdout);
int i,j,k;
int a,b,c;
scanf("%d%d",&n,&m);
dcount=1;
for(i=1;i<=m;i++)
{
scanf("%d",&a);
if(a==1)
{
scanf("%d%d",&b,&c);
add(c,b);
visit[b]=1;
}
if(a==2)
{
scanf("%d",&b);
crs[dcount++]=b;
}
if(a==3)
{
scanf("%d%d",&b,&c);
if(c>=dcount)++cntq;
else addq(b,crs[c],c);
}
}
for(i=1;i<=n;i++)f[i]=i;
for(i=1;i<=n;i++)
{
if(!visit[i])dfs(i,i,0);
}
for(i=1;i<=cntq;i++)
{
if(ans[i])puts("YES");
else puts("NO");
}
return 0;
}