我靠!写的东西总被坑爹又不稳定的博客频道吞掉,我已经无力吐槽,也无力再写了!
简单写写题意题解。
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”。
代码:可以去看我的tarjan lca,里面有这种算法的思想(自创)。
http://blog.csdn.net/vmurder/article/details/38734663
#include <cstdio> #include <algorithm> #define N 5001000 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(f[x]); l[x]=max(l[x],l[t]); return f[x]; } inline void dfs(int x,int p,int ll) { int i; visit[x]=1; 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); 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); } 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; }