听说KPM初二暑假就补完了啊%%%

  先刷Gold再刷Silver(因为目测没那么多时间刷Silver,方便以后TJ2333(雾

  按AC数降序刷

-------------------------------------------------------------------------------------------------------

  bzoj1597: [Usaco2008 Mar]土地购买 

    斜率优化DP

    h升序,w降序。

    f[i]=min(f[j]+h[i]*w[j+1])

    (h[j]-h[k])/(w[k+1]-w[j+1])<h[i]

    所以下凸,斜率不下降

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<queue>
  6. #include<algorithm>
  7. #define ll long long
  8. using namespace std;
  9. const int maxn=;
  10. struct poi{int h,w;}a[maxn];
  11. int n,m,x,y,z,l,r,tot,h[maxn],w[maxn];
  12. ll q[maxn],f[maxn];
  13. void read(int &k)
  14. {
  15. int f=;k=;char c=getchar();
  16. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  17. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  18. k*=f;
  19. }
  20. bool cmp(poi a,poi b){return a.h==b.h?a.w<b.w:a.h<b.h;}
  21. double xl(int x,int y){return (f[y]-f[x])/(w[x+]-w[y+]);}
  22. int main()
  23. {
  24. read(n);
  25. for(int i=;i<=n;i++)read(a[i].h),read(a[i].w);
  26. sort(a+,a++n,cmp);
  27. for(int i=;i<=n;i++)
  28. {
  29. while(tot&&w[tot]<=a[i].w)tot--;
  30. h[++tot]=a[i].h;w[tot]=a[i].w;
  31. }
  32. l=;r=;
  33. for(int i=;i<=tot;i++)
  34. {
  35. while(l<r&&xl(q[l],q[l+])<h[i])l++;
  36. f[i]=f[q[l]]+1ll*h[i]*w[q[l]+];
  37. while(l<r&&xl(q[r-],q[r])>xl(q[r],i))r--;
  38. q[++r]=i;
  39. }
  40. printf("%lld\n",f[tot]);
  41. return ;
  42. }

  bzoj1699: [Usaco2007 Jan]Balanced Lineup排队

    裸RMQ

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<cmath>
  6. using namespace std;
  7. int n,m,f[][],g[][],l,r,k;
  8. void read(int &k)
  9. {
  10. int f=;k=;char c=getchar();
  11. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  12. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  13. k*=f;
  14. }
  15. int log2(int x){return log(x)/log();}
  16. int exp(int x){return <<x;}
  17. void rmq()
  18. {
  19. for(int j=;j<=log2(n);j++)
  20. for(int i=;i<=n-exp(j)+;i++)
  21. f[i][j]=max(f[i][j-],f[i+exp(j-)][j-]),g[i][j]=min(g[i][j-],g[i+exp(j-)][j-]);
  22. }
  23. int main()
  24. {
  25. read(n);read(m);
  26. for(int i=;i<=n;i++)read(f[i][]),g[i][]=f[i][];
  27. rmq();
  28. for(int i=;i<=m;i++)
  29. {
  30. read(l);read(r);
  31. k=log2(r-l+);
  32. printf("%d\n",max(f[l][k],f[r-exp(k)+][k])-min(g[l][k],g[r-exp(k)+][k]));
  33. }
  34. }

  bzoj1666: [Usaco2006 Oct]Another Cow Number Game 奶牛的数字游戏

    直接模拟

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. using namespace std;
  6. void read(int &k)
  7. {
  8. int f=;k=;char c=getchar();
  9. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  10. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  11. k*=f;
  12. }
  13. int ans,n;
  14. int main()
  15. {
  16. read(n);
  17. while(n!=)
  18. {
  19. ans++;
  20. if(n&)n=n*+;
  21. else n/=;
  22. }
  23. printf("%d\n",ans);
  24. }

  bzoj1692: [Usaco2007 Dec]队列变换

    hash+二分logn比较正反后缀字典序

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #define ull unsigned long long
  6. using namespace std;
  7. ull mul[],hs[],ophs[],L,R,l,r,mid,len,num,n;
  8. char s[];
  9. void read(ull &k)
  10. {
  11. int f=;k=;char c=getchar();
  12. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  13. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  14. k*=f;
  15. }
  16. int lcp()
  17. {
  18. l=;r=R-L+;
  19. while(l<r)
  20. {
  21. mid=(l+r+)>>;
  22. int hs1=hs[L+mid-]-hs[L-]*mul[mid];
  23. int hs2=ophs[R-mid+]-ophs[R+]*mul[mid];
  24. if(hs1!=hs2)r=mid-;else l=mid;
  25. }
  26. return l;
  27. }
  28. bool cmp()
  29. {
  30. if(s[L]!=s[R])return s[L]>s[R];
  31. len=lcp();
  32. if(len==R-L+)return ;
  33. else return s[L+len]>s[R-len];
  34. }
  35. int main()
  36. {
  37. read(n);
  38. for(int i=;i<=n;i++)
  39. for(s[i]=getchar();s[i]<'A'||s[i]>'Z';s[i]=getchar());
  40. mul[]=;
  41. for(int i=;i<=n;i++)mul[i]=mul[i-]*;
  42. for(int i=;i<=n;i++)hs[i]=hs[i-]*+(ull)s[i]-'A';
  43. for(int i=n;i;i--)ophs[i]=ophs[i+]*+(ull)s[i]-'A';
  44. L=;R=n;num=;
  45. for(int i=;i<=n;i++,num++)
  46. {
  47. printf("%c",cmp()?s[R--]:s[L++]);
  48. if(num==)printf("\n"),num=;
  49. }
  50. }

  bzoj1717: [Usaco2006 Dec]Milk Patterns 产奶的模式

    可重叠k次最长重复子串

    二分答案,h[]>=mid的分一段,如果有一段的后缀个数>=k则合法。

    多关键字基数排序。

    a[]为A关键字

    b[]为B关键字排序后的数组(作为排序后数组的答案)

    for(int i=1;i<=n;i++)sum[a[i]]++;
    for(int i=1;i<=n;i++)sum[i]+=sum[i-1];
    for(int i=n;i;i--)sa[sum[a[b[i]]]=b[i],sum[a[b[i]]]--;

    而在SA中

    for(int i=1;i<=n;i++)rk[i]=trk[tsa[i]],sum[rk[i]]++;
    for(int i=2;i<=m;i++)sum[i]+=sum[i-1];
    for(int i=n;i;i--)sa[sum[rk[i]]]=tsa[i],sum[rk[i]]--;

    A B关键字就是字符的字典序。

    a[]实际上是trk[]

    b[]是tsa[]

    定义了一个rk[]=trk[tsa[]]

    那么多关键字排序的时候就sa[sum[trk[tsa[]]]]变成了sa[sum[rk[]]]。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. using namespace std;
  6. const int maxn=;
  7. int n,m,p,k,l,r;
  8. int sum[maxn],rk[maxn],sa[maxn],trk[maxn],tsa[maxn],h[maxn],s[maxn];
  9. void read(int &k)
  10. {
  11. int f=;k=;char c=getchar();
  12. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  13. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  14. k*=f;
  15. }
  16. void suffix()
  17. {
  18. for(int i=;i<=n;i++)sum[s[i]]++;
  19. for(int i=;i<=;i++)sum[i]+=sum[i-];
  20. for(int i=n;i;i--)sa[sum[s[i]]]=i,sum[s[i]]--;
  21. rk[sa[]]=;p=;
  22. for(int i=;i<=n;i++)rk[sa[i]]=(s[sa[i]]!=s[sa[i-]])?++p:p;
  23. m=p;int j=;
  24. while(m<n)
  25. {
  26. memcpy(trk,rk,sizeof(rk));memset(sum,,sizeof(sum));p=;
  27. for(int i=n-j+;i<=n;i++)tsa[++p]=i;
  28. for(int i=;i<=n;i++)if(sa[i]>j)tsa[++p]=sa[i]-j;
  29. for(int i=;i<=n;i++)rk[i]=trk[tsa[i]],sum[rk[i]]++;
  30. for(int i=;i<=m;i++)sum[i]+=sum[i-];
  31. for(int i=n;i;i--)sa[sum[rk[i]]]=tsa[i],sum[rk[i]]--;
  32. rk[sa[]]=;p=;
  33. for(int i=;i<=n;i++)rk[sa[i]]=(trk[sa[i]]!=trk[sa[i-]]||trk[sa[i]+j]!=trk[sa[i-]+j])?++p:p;
  34. m=p;j*=;
  35. }
  36. h[]=;p=;
  37. for(int i=;i<=n;i++)
  38. {
  39. if(rk[i]==)continue;
  40. j=sa[rk[i]-];
  41. while(s[i+p]==s[j+p])p++;
  42. h[rk[i]]=p;
  43. if(p)p--;
  44. }
  45. }
  46. bool check(int mid)
  47. {
  48. int num=;
  49. for(int i=;i<=n;i++)
  50. if(h[i]>=mid)num++;
  51. else
  52. {
  53. if(num>=k)return ;
  54. num=;
  55. }
  56. if(num>=k)return ;
  57. return ;
  58. }
  59. int main()
  60. {
  61. read(n);read(k);
  62. for(int i=;i<=n;i++)read(s[i]);
  63. suffix();
  64. l=;r=n;
  65. while(l<r)
  66. {
  67. int mid=(l+r+)>>;
  68. if(check(mid))l=mid;
  69. else r=mid-;
  70. }
  71. printf("%d\n",l);
  72. }

  bzoj1724: [Usaco2006 Nov]Fence Repair 切割木板

    堆,每次合并最小的两个木板

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<queue>
  6. #define ll long long
  7. using namespace std;
  8. struct poi{int sum;};
  9. priority_queue<poi>q;
  10. bool operator <(poi a,poi b){return a.sum>b.sum;};
  11. int x,y,n;
  12. ll ans;
  13. void read(int &k)
  14. {
  15. int f=;k=;char c=getchar();
  16. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  17. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  18. k*=f;
  19. }
  20. int main()
  21. {
  22. read(n);
  23. for(int i=;i<=n;i++)read(x),q.push((poi){x});
  24. for(int i=;i<n;i++)
  25. {
  26. x=q.top().sum;q.pop();
  27. y=q.top().sum;q.pop();
  28. ans+=x+y;
  29. q.push((poi){x+y});
  30. }
  31. printf("%lld\n",ans);
  32. }

  bzoj1572: [Usaco2009 Open]工作安排Job

    能加就加;加不进去还是加进去,然后删掉最小的。

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #define ll long long
  8. using namespace std;
  9. struct poi{ll d,p;}a[];
  10. struct tjm{ll p;};
  11. priority_queue<tjm>q;
  12. bool operator<(tjm a,tjm b){return a.p>b.p;}
  13. ll n,x,t;
  14. long long ans;
  15. void read(ll &k)
  16. {
  17. int f=;k=;char c=getchar();
  18. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  19. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  20. k*=f;
  21. }
  22. bool cmp(poi a,poi b){return (a.d<b.d)||((a.d==b.d)&&(a.p>b.p));}
  23. int main()
  24. {
  25. read(n);
  26. for(int i=;i<=n;i++)read(a[i].d),read(a[i].p);
  27. sort(a+,a++n,cmp);
  28. t=;
  29. for(int i=;i<=n;i++)
  30. {
  31. if(a[i].d<t)
  32. {
  33. x=q.top().p;
  34. if(a[i].p>x)
  35. {
  36. ans=ans-x+a[i].p;
  37. q.pop();
  38. q.push((tjm){a[i].p});
  39. }
  40. }
  41. else
  42. {
  43. t++;
  44. q.push((tjm){a[i].p});
  45. ans+=a[i].p;
  46. }
  47. }
  48. printf("%lld\n",ans);
  49. }

  bzoj1726: [Usaco2006 Nov]Roadblocks第二短路

    次短路模板

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. using namespace std;
  6. const int inf=,maxn=,maxm=;
  7. struct zs{int too,sum,pre;}e[maxm];
  8. int n,m,tot,front,rear;
  9. int dist[maxn],dist2[maxn],v[maxn],last[maxn],h[maxm],x,y,z;
  10. void read(int &k)
  11. {
  12. int f=;k=;char c=getchar();
  13. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  14. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  15. k*=f;
  16. }
  17. void add(int x,int y,int z){e[++tot].too=y;e[tot].sum=z;e[tot].pre=last[x];last[x]=tot;}
  18. void spfa(int x)
  19. {
  20. for(int i=;i<=n;i++)dist[i]=inf,dist2[i]=inf,v[i]=;
  21. v[x]=;dist[x]=;rear=;front=;h[]=x;
  22. while(front!=rear)
  23. {
  24. int now=h[++front];if(front==maxm)front=-;
  25. for(int i=last[now];i;i=e[i].pre)
  26. {
  27. int too=e[i].too,dis=dist[now]+e[i].sum;
  28. bool flag=;
  29. if(dist[too]>dis)dist2[too]=dist[too],dist[too]=dis,flag=;
  30. if(dist[too]<dis&&dist2[too]>dis)dist2[too]=dis,flag=;
  31. if(dist2[too]>dist2[now]+e[i].sum)dist2[too]=dist2[now]+e[i].sum,flag=;
  32. if(flag&&!v[too])
  33. {
  34. v[too]=;
  35. h[++rear]=too;
  36. if(rear==maxm)rear=-;
  37. }
  38. }
  39. v[now]=;
  40. }
  41. }
  42. int main()
  43. {
  44. read(n);read(m);
  45. for(int i=;i<=m;i++)
  46. read(x),read(y),read(z),add(x,y,z),add(y,x,z);
  47. spfa();
  48. printf("%d\n",dist2[n]);
  49. return ;
  50. }

  bzoj1579: [Usaco2009 Feb]Revamping Trails 道路升级

    分层图(优先队列好慢。。。但是不会被卡

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. #include<queue>
  6. #define ll long long
  7. using namespace std;
  8. const int inf=,maxn=,maxm=;
  9. struct poi{ll dis,pos,ceng;};
  10. struct zs{int too,sum,pre;}e[maxm];
  11. priority_queue<poi>q;
  12. bool operator<(poi a,poi b){return a.dis>b.dis;}
  13. int n,m,k,tot,x,y,z,last[maxn];;
  14. ll dist[maxn][],ans;
  15. bool v[maxn][];
  16. void read(int &k)
  17. {
  18. int f=;k=;char c=getchar();
  19. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  20. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  21. k*=f;
  22. }
  23. void add(int x,int y,int z){e[++tot].too=y;e[tot].sum=z;e[tot].pre=last[x];last[x]=tot;}
  24. void spfa(int x)
  25. {
  26. for(int i=;i<=n;i++)for(int j=;j<=k;j++)dist[i][j]=inf,v[i][j]=;
  27. v[x][]=;dist[x][]=;q.push((poi){,x});
  28. while(!q.empty())
  29. {
  30. poi now=q.top();int ceng=now.ceng;q.pop();
  31. for(int i=last[now.pos];i;i=e[i].pre)
  32. {
  33. int too=e[i].too;
  34. if(dist[too][ceng]>dist[now.pos][ceng]+e[i].sum)
  35. {
  36. dist[too][ceng]=dist[now.pos][ceng]+e[i].sum;
  37. if(!v[too][ceng])
  38. {
  39. v[too][ceng]=;
  40. q.push((poi){dist[too][ceng],too,ceng});
  41. }
  42. }
  43. if(dist[too][ceng+]>dist[now.pos][ceng]&&ceng<k)
  44. {
  45. dist[too][ceng+]=dist[now.pos][ceng];
  46. if(!v[too][ceng+])
  47. {
  48. v[too][ceng+]=;
  49. q.push((poi){dist[too][ceng+],too,ceng+});
  50. }
  51. }
  52. }
  53. v[now.pos][ceng]=;
  54. }
  55. }
  56. int main()
  57. {
  58. read(n);read(m);read(k);
  59. for(int i=;i<=m;i++)read(x),read(y),read(z),add(x,y,z),add(y,x,z);
  60. spfa();
  61. ans=inf;
  62. for(int i=;i<=k;i++)
  63. ans=min(ans,dist[n][i]);
  64. printf("%lld\n",ans);
  65. }

  bzoj1690: [Usaco2007 Dec]奶牛的旅行

    最优比率环。以前写过篇题解,当时没有真的懂,看了一下分数规划终于明白了。已经更新以前的题解

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. #include<queue>
  6. using namespace std;
  7. struct zs{int too,pre;double dis;}e[];
  8. struct poi{int pos;double dis;};
  9. priority_queue<poi>q;
  10. bool operator <(poi a,poi b){return a.dis-b.dis>1e-;}
  11. int n,m,x,y,now,tot,num[],last[];
  12. bool v[];
  13. double l,r,mid,dis[],fun[];
  14. bool spfa(int x)
  15. {
  16. for(int i=;i<=n;i++)dis[i]=;v[x]=true;q.push((poi){,});dis[]=;
  17. while(!q.empty())
  18. {
  19. int i,too;
  20. for(i=last[now=q.top().pos],too=e[i].too,q.pop();i;i=e[i].pre,too=e[i].too)
  21. {
  22. double dist=e[i].dis*mid-fun[too];
  23. if(dis[too]-dis[now]-dist>1e-)
  24. {
  25. dis[too]=dis[now]+dist;
  26. if(!v[too])v[too]=,q.push((poi){too,e[i].dis}),num[too]++;
  27. if(num[too]>)return ;
  28. }
  29. }
  30. v[now]=;
  31. }
  32. return ;
  33. }
  34. int main()
  35. {
  36. scanf("%d %d",&n,&m);
  37. for(int i=;i<=n;i++)scanf("%lf",&fun[i]);
  38. for(int i=;i<=m;i++)
  39. {
  40. scanf("%d %d %lf",&x,&y,&e[++tot].dis);
  41. e[tot].too=y;e[tot].pre=last[x];last[x]=tot;
  42. }
  43. l=;r=;
  44. while(r-l>1e-)
  45. {
  46. memset(v,,sizeof(v));
  47. memset(num,,sizeof(num));
  48. mid=(l+r)/;
  49. if(spfa())l=mid;
  50. else r=mid;
  51. }
  52. printf("%.2lf",l);
  53. }

  bzoj1711: [Usaco2007 Open]Dining吃饭

    三分图,牛i拆成i和i',S连食物,食物连i,i'连饮料,饮料连T,最大流。

    脑洞大开问了下CZL,如果有多一种种类的话就把牛右边改成100*100个点表示另外两种怎么选,自己yy的写法被CZL随手叉掉,还学习了一波随机化的姿势和卡掉随机化的姿势,受益匪浅嘿嘿嘿

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. using namespace std;
  6. const int inf=,maxn=;
  7. struct poi{int too,pre,cf;}e[];
  8. int n,m,tot,ans,x,y,z,front,rear,fd,dk,ffd,ddk,sum;
  9. int h[maxn],v[maxn],last[maxn],dis[maxn],cur[maxn];
  10. void read(int &k)
  11. {
  12. int f=;k=;char c=getchar();
  13. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  14. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  15. k*=f;
  16. }
  17. void add(int x,int y,int z)
  18. {
  19. e[++tot].too=y;e[tot].cf=z;e[tot].pre=last[x];last[x]=tot;
  20. e[++tot].too=x;e[tot].pre=last[y];last[y]=tot;
  21. }
  22. bool bfs()
  23. {
  24. for(int i=;i<=sum;i++)v[i]=,dis[i]=-;
  25. dis[]=;v[]=;h[]=;front=;rear=;
  26. while(front!=rear)
  27. {
  28. int now=h[++front];if(front==maxn)front=-;
  29. for(int i=last[now];i;i=e[i].pre)
  30. {
  31. int too=e[i].too;
  32. if(!v[too]&&e[i].cf)
  33. {
  34. dis[too]=dis[now]+;if(too==sum)return ;
  35. v[too]=;h[++rear]=too;if(rear==maxn)rear=-;
  36. }
  37. }
  38. }
  39. return ;
  40. }
  41. int dfs(int x,int f)
  42. {
  43. int flow=,tmp;
  44. if(x==sum)return f;
  45. for(int &i=cur[x];i;i=e[i].pre)
  46. {
  47. int too=e[i].too;
  48. if(dis[too]==dis[x]+&&e[i].cf)
  49. {
  50. tmp=dfs(too,min(f-flow,e[i].cf));
  51. e[i].cf-=tmp;e[i^].cf+=tmp;flow+=tmp;
  52. if(f==flow)return f;
  53. }
  54. }
  55. return flow;
  56. }
  57. void dinic()
  58. {
  59. while(bfs())
  60. {
  61. for(int i=;i<=sum;i++)cur[i]=last[i];
  62. ans+=dfs(,inf);
  63. }
  64. }
  65. int main()
  66. {
  67. tot=;
  68. read(n);read(fd);read(dk);sum=fd+n*+dk+;
  69. for(int i=;i<=fd;i++)add(,i,);
  70. for(int i=;i<=dk;i++)add(i+fd+n*,sum,);
  71. for(int i=;i<=n;i++)add(i+fd,i+n+fd,);
  72. for(int i=;i<=n;i++)
  73. {
  74. read(ffd);read(ddk);
  75. for(int j=;j<=ffd;j++)
  76. {
  77. read(x);
  78. add(x,i+fd,);
  79. }
  80. for(int j=;j<=ddk;j++)
  81. {
  82. read(x);
  83. add(i+n+fd,x+fd+n*,);
  84. }
  85. }
  86. dinic();
  87. printf("%d\n",ans);
  88. }

  bzoj1708: [Usaco2007 Oct]Money奶牛的硬币

    裸完全(无限?)背包。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #define ll long long
  6. using namespace std;
  7. ll n,v,x,f[];
  8. void read(ll &k)
  9. {
  10. int f=;k=;char c=getchar();
  11. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  12. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  13. k*=f;
  14. }
  15. int main()
  16. {
  17. read(v);read(n);
  18. f[]=;
  19. for(int i=;i<=v;i++)
  20. {
  21. read(x);
  22. for(int j=x;j<=n;j++)
  23. f[j]+=f[j-x];
  24. }
  25. printf("%lld\n",f[n]);
  26. return ;
  27. }

  bzoj1827: [Usaco2010 Mar]gather 奶牛大集会

    树上处理题。第一次dfs记录下size[x]表示子树有几只牛和dis[x]表示子树所有牛到x的距离,第二次求总距离,每次到子节点时,总距离就加上边权*(n-size[son]),减去边权*(n-size[son]),也就是加上边权*(n-2*size[son])。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #define ll long long
  6. using namespace std;
  7. const int maxn=;
  8. struct poi{int too,pre,sum;}e[];
  9. int last[maxn];
  10. ll n,x,y,z,tot,cnt;
  11. ll dis[maxn],size[maxn],ans;
  12. void read(ll &k)
  13. {
  14. int f=;k=;char c=getchar();
  15. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  16. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  17. k*=f;
  18. }
  19. void add(int x,int y,int z){e[++tot].too=y;e[tot].sum=z;e[tot].pre=last[x];last[x]=tot;}
  20. void dfs(int x,int fa)
  21. {
  22. for(int i=last[x];i;i=e[i].pre)
  23. {
  24. if(e[i].too==fa)continue;
  25. dfs(e[i].too,x);
  26. size[x]+=size[e[i].too];
  27. dis[x]+=dis[e[i].too]+size[e[i].too]*e[i].sum;
  28. }
  29. }
  30. void dfs2(int x,int fa,ll dist)
  31. {
  32. ans=min(ans,dist);
  33. for(int i=last[x];i;i=e[i].pre)
  34. {
  35. if(e[i].too==fa)continue;
  36. ll sum=e[i].sum*(cnt-*size[e[i].too]);
  37. dfs2(e[i].too,x,dist+sum);
  38. }
  39. }
  40. int main()
  41. {
  42. read(n);
  43. for(int i=;i<=n;i++)read(size[i]),cnt+=size[i];
  44. for(int i=;i<n;i++)read(x),read(y),read(z),add(x,y,z),add(y,x,z);
  45. dfs(,);
  46. ans=dis[];
  47. dfs2(,,dis[]);
  48. printf("%lld\n",ans);
  49. return ;
  50. }

  bzoj1725: [Usaco2006 Nov]Corn Fields牧场的安排

    状压

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. #define ll long long
  6. using namespace std;
  7. void read(int &k)
  8. {
  9. int f=;k=;char c=getchar();
  10. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  11. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  12. k*=f;
  13. }
  14. int n,m,x;
  15. ll ans,f[][],state[];
  16. bool v[];
  17. int main()
  18. {
  19. read(n);read(m);
  20. for(int i=;i<=n;i++)
  21. {
  22. for(int j=;j<=m;j++)
  23. {
  24. read(x);
  25. if(x)
  26. state[i]|=(<<(j-));
  27. }
  28.  
  29. }
  30. int st=(<<m)-;
  31. v[]=;
  32. for(int i=;i<=st;i++)
  33. {
  34. int flag=;
  35. for(int j=;j<m;j++)
  36. if((((i>>(j-))&))&((i>>j)&)==)
  37. {
  38. flag=;
  39. break;
  40. }
  41. v[i]=flag;
  42. }
  43. f[][]=;
  44. for(int i=;i<=n;i++)
  45. for(int j=;j<=st;j++)
  46. if(v[j])
  47. if((j|state[i])==state[i])
  48. for(int k=;k<=st;k++)
  49. if(v[k])
  50. if((k|state[i-])==state[i-])
  51. if((j&k)==)
  52. f[i][j]=(f[i][j]+f[i-][k])%;
  53. for(int i=;i<=st;i++)
  54. ans=(ans+f[n][i])%;
  55. printf("%lld\n",ans);
  56. return ;
  57. }

  bzoj1592: [Usaco2008 Feb]Making the Grade 路面修整

    首先可以证明一个结论,最后修改出的序列的数字还是原序列的数字,因为是不下降或者不上升,直接改到一样显然是最优的,不然必然会多改一点。

    于是把高度离散化,枚举i和高度就行了,前一个路面的高度可以直接记录最小值。

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<cmath>
  7. using namespace std;
  8. const int maxn=,inf=;
  9. struct poi{int pos,sum;}a[maxn];
  10. int n,ht[maxn],lisan[maxn],ans,f[maxn][maxn];
  11. void read(int &k)
  12. {
  13. int f=;k=;char c=getchar();
  14. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  15. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  16. k*=f;
  17. }
  18. bool cmp(poi a,poi b){return a.sum<b.sum;}
  19. int main()
  20. {
  21. read(n);
  22. for(int i=;i<=n;i++)read(a[i].sum),a[i].pos=i;
  23. sort(a+,a++n,cmp);
  24. for(int i=;i<=n;i++)ht[a[i].pos]=a[i].sum,lisan[a[i].pos]=i;
  25. for(int i=;i<=n;i++)for(int j=;j<=n;j++)f[i][j]=inf;
  26. for(int i=;i<=n;i++)f[][i]=;
  27. for(int i=;i<=n;i++)
  28. {
  29. int mn=inf;
  30. for(int j=;j<=n;j++)
  31. {
  32. mn=min(mn,f[i-][j]);
  33. f[i][j]=min(f[i][j],mn)+abs(a[j].sum-ht[i]);
  34. }
  35. }
  36. ans=f[n][];
  37. for(int i=;i<=n;i++)ans=min(ans,f[n][i]);
  38. for(int i=;i<=n;i++)for(int j=;j<=n;j++)f[i][j]=inf;
  39. for(int i=;i<=n;i++)f[][i]=;
  40. lisan[]=n;
  41. for(int i=;i<=n;i++)
  42. {
  43. int mn=inf;
  44. for(int j=n;j;j--)
  45. {
  46. mn=min(mn,f[i-][j]);
  47. f[i][j]=min(f[i][j],mn)+abs(a[j].sum-ht[i]);
  48. }
  49. }
  50. for(int i=;i<=n;i++)ans=min(ans,f[n][i]);
  51. printf("%d\n",ans);
  52. }

  bzoj2442: [Usaco2011 Open]修剪草坪

    DP+单调队列优化

    学会了DP的巧妙姿势,如果可以选和不选求最大值可以尝试直接求不选的最小值,好写很多。

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<cmath>
  7. #define ll long long
  8. using namespace std;
  9. const int maxn=;
  10. int n,k,a[maxn],q[maxn],l,r;
  11. ll sum,ans,f[maxn];
  12. void read(int &k)
  13. {
  14. int f=;k=;char c=getchar();
  15. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  16. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  17. k*=f;
  18. }
  19. int main()
  20. {
  21. read(n);read(k);
  22. for(int i=;i<=n;i++)read(a[i]),sum+=a[i];
  23. for(int i=;i<=n;i++)
  24. {
  25. while((i-q[l]>k+)&&(l<=r))l++;
  26. f[i]=f[q[l]]+a[i];
  27. while((l<=r)&&(f[i]<f[q[r]]))r--;
  28. q[++r]=i;
  29. }
  30. ans=;
  31. for(int i=n-k;i<=n;i++)
  32. ans=min(ans,f[i]);
  33. printf("%lld\n",sum-ans);
  34. return ;
  35. }

  bzoj1576: [Usaco2009 Jan]安全路经Travel

    树链剖分或并查集。树剖以后补。

    跑出最短路径树就是这题了。

树链剖分:

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<queue>
  6. #define ll long long
  7. using namespace std;
  8. const int maxn=,inf=;
  9. struct gg{int dis,pos;};
  10. priority_queue<gg>q;
  11. bool operator<(gg a,gg b){return a.dis>b.dis;}
  12. struct poi{int x,too,pre,sum;}e[maxn];
  13. struct tjm{int sum,tag;}a[maxn];
  14. struct zs{int x,y,len;}edge[maxn];
  15. int n,m,x,y,z,flag,tot,tot2,cnt;
  16. int last[maxn],size[maxn],fa[maxn],dep[maxn],son[maxn],w[maxn],top[maxn],dist[maxn],eg[maxn];
  17. bool used[maxn];
  18. void read(int &k)
  19. {
  20. int f=;k=;char c=getchar();
  21. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  22. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  23. k*=f;
  24. }
  25. void add(int x,int y,int z){e[++tot].too=y;e[tot].x=x;e[tot].sum=z;e[tot].pre=last[x];last[x]=tot;}
  26. void dfs1(int x)
  27. {
  28. size[x]=;
  29. for(int i=last[x];i;i=e[i].pre)
  30. {
  31. int too=e[i].too;
  32. if(fa[too]==x&&too!=fa[x])
  33. {
  34. dep[too]=dep[x]+e[i].sum;
  35. dfs1(too);
  36. if(size[too]>size[son[x]])son[x]=too;
  37. size[x]+=size[too];
  38. }
  39. }
  40. }
  41. void dfs2(int x,int tp)
  42. {
  43. w[x]=++cnt;top[x]=tp;
  44. if(son[x])dfs2(son[x],tp);
  45. for(int i=last[x];i;i=e[i].pre)
  46. if(e[i].too!=son[x]&&e[i].too!=fa[x]&&fa[e[i].too]==x)
  47. dfs2(e[i].too,e[i].too);
  48. }
  49. void pushdown(int x)
  50. {
  51. if(a[x].tag==inf)return;
  52. int tag=a[x].tag;a[x].tag=inf;
  53. a[x<<].tag=min(tag,a[x<<].tag);
  54. a[x<<|].tag=min(tag,a[x<<|].tag);
  55. }
  56. void update(int x,int nl,int nr,int l,int r,int delta)
  57. {
  58. if(l<=nl&&nr<=r)a[x].tag=min(a[x].tag,delta);
  59. else
  60. {
  61. int mid=(nl+nr)>>;
  62. if(l<=mid)update(x<<,nl,mid,l,r,delta);
  63. if(r>mid)update(x<<|,mid+,nr,l,r,delta);
  64. }
  65. }
  66. ll query(int x,int nl,int nr,int num)
  67. {
  68. if(nl!=nr)pushdown(x);
  69. if(nl==num&&nr==num)return a[x].tag;
  70. else
  71. {
  72. int mid=(nl+nr)>>;
  73. if(nl<=num&&num<=mid)return query(x<<,nl,mid,num);
  74. if(mid<num&&num<=nr)return query(x<<|,mid+,nr,num);
  75. }
  76. }
  77. void work(int x,int y,int len)
  78. {
  79. int f1=top[x],f2=top[y];
  80. while(f1!=f2)
  81. {
  82. if(dep[f1]<dep[f2])swap(x,y),swap(f1,f2);
  83. update(,,cnt,w[f1],w[x],len);
  84. x=fa[f1];f1=top[x];
  85. }
  86. if(x==y)return;
  87. if(dep[x]<dep[y])swap(x,y);
  88. update(,,cnt,w[son[y]],w[x],len);
  89. }
  90. void build(int x,int l,int r)
  91. {
  92. a[x].tag=inf;int mid=(l+r)>>;
  93. if(l!=r)build(x<<,l,mid),build(x<<|,mid+,r);
  94. }
  95. void spfa(int x)
  96. {
  97. bool v[maxn];
  98. for(int i=;i<=n;i++)dist[i]=inf,v[i]=;
  99. v[x]=;dist[x]=;q.push((gg){,x});
  100. while(!q.empty())
  101. {
  102. int now=q.top().pos;q.pop();
  103. for(int i=last[now];i;i=e[i].pre)
  104. {
  105. int too=e[i].too;
  106. if(dist[too]>dist[now]+e[i].sum)
  107. {
  108. dist[too]=dist[now]+e[i].sum;
  109. dep[too]=dep[now]+e[i].sum;
  110. fa[too]=now;eg[too]=i;
  111. if(!v[too])
  112. {
  113. v[too]=;
  114. q.push((gg){dist[too],too});
  115. }
  116. }
  117. }
  118. v[now]=;
  119. }
  120. }
  121. int main()
  122. {
  123. tot=;
  124. read(n);read(m);
  125. for(int i=;i<=m;i++)
  126. {
  127. read(x);read(y);read(z);
  128. add(x,y,z),add(y,x,z);
  129. }
  130. spfa();
  131. for(int i=;i<=n;i++)used[eg[i]]=used[eg[i]^]=;
  132. for(int i=;i<=tot;i++)
  133. if(!used[i])
  134. {
  135. edge[++tot2].x=e[i].x;edge[tot2].y=e[i].too;
  136. edge[tot2].len=e[i].sum+dep[e[i].x]+dep[e[i].too];
  137. }
  138. dfs1();dfs2(,);build(,,n);
  139. for(int i=;i<=tot2;i++)
  140. work(edge[i].x,edge[i].y,edge[i].len);
  141. for(int i=;i<=n;i++)
  142. {
  143. int ans=query(,,cnt,w[i]);
  144. if(ans!=inf)printf("%d\n",ans-dep[i]);
  145. else printf("-1\n");
  146. }
  147. return ;
  148. }

并查集:

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. #include<queue>
  6. #include<algorithm>
  7. using namespace std;
  8. const int inf=,maxn=;
  9. struct zs{int x,too,sum,pre;}e[maxn];
  10. struct poi{int dis,pos;};
  11. struct tjm{int len,x,y;}edge[maxn];
  12. priority_queue<poi>q;
  13. bool operator<(poi a,poi b){return a.dis>b.dis;}
  14. int n,m,x,y,z,tot,tot2;
  15. int last[maxn],dist[maxn],h[maxn],fq[maxn],eg[maxn],fa[maxn],v[maxn];
  16. bool used[maxn];
  17. void read(int &k)
  18. {
  19. int f=;k=;char c=getchar();
  20. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  21. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  22. k*=f;
  23. }
  24. void add(int x,int y,int z){e[++tot].x=x;e[tot].too=y;e[tot].sum=z;e[tot].pre=last[x];last[x]=tot;}
  25. void spfa(int x)
  26. {
  27. bool v[maxn];
  28. for(int i=;i<=n;i++)dist[i]=inf,v[i]=;
  29. v[x]=;dist[x]=;q.push((poi){,x});
  30. while(!q.empty())
  31. {
  32. int now=q.top().pos;q.pop();
  33. for(int i=last[now];i;i=e[i].pre)
  34. {
  35. int too=e[i].too;
  36. if(dist[too]>dist[now]+e[i].sum)
  37. {
  38. dist[too]=dist[now]+e[i].sum;
  39. h[too]=h[now]+e[i].sum;
  40. fq[too]=now;eg[too]=i;
  41. if(!v[too])
  42. {
  43. v[too]=;
  44. q.push((poi){dist[too],too});
  45. }
  46. }
  47. }
  48. v[now]=;
  49. }
  50. }
  51. bool cmp(tjm a,tjm b){return a.len<b.len;}
  52. int gf(int x){return fa[x]==x?x:fa[x]=gf(fa[x]);}
  53. int main()
  54. {
  55. tot=;
  56. read(n);read(m);
  57. for(int i=;i<=m;i++)read(x),read(y),read(z),add(x,y,z),add(y,x,z);
  58. spfa();
  59. for(int i=;i<=n;i++)used[eg[i]]=used[eg[i]^]=;
  60. for(int i=;i<=tot;i++)
  61. if(!used[i])
  62. {
  63. edge[++tot2].x=e[i].x;edge[tot2].y=e[i].too;
  64. edge[tot2].len=e[i].sum+h[e[i].x]+h[e[i].too];
  65. }
  66. sort(edge+,edge++tot2,cmp);
  67. for(int i=;i<=n;i++)fa[i]=i;
  68. for(int i=;i<=tot2;i++)
  69. {
  70. int x=edge[i].x,y=edge[i].y,f1=gf(x),f2=gf(y),lastx=,lasty=;
  71. while(f1!=f2)
  72. {
  73. if(h[f1]<h[f2])swap(x,y),swap(f1,f2),swap(lastx,lasty);
  74. if(!v[x])
  75. {
  76. v[x]=i;
  77. if(lastx)fa[lastx]=x;
  78. }else if(lastx)fa[lastx]=f1;
  79. lastx=f1;x=fq[lastx];f1=gf(x);
  80. }
  81. }
  82. for(int i=;i<=n;i++)
  83. if(v[i])printf("%d\n",edge[v[i]].len-h[i]);
  84. else printf("-1\n");
  85. }

  bzoj1782: [Usaco2010 Feb]slowdown 慢慢游

    其实就是求每个节点到根的路径上比自己小的节点有几个,BIT维护一下就行了。

    好像网上题解有其他写法,等等去学习一下姿势

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<queue>
  6. #include<algorithm>
  7. #define ll long long
  8. using namespace std;
  9. const int maxn=;
  10. struct poi{int too,pre;}e[maxn];
  11. int n,m,x,y,z,tot;
  12. int a[maxn],p[maxn],ans[maxn],last[maxn],v[maxn];
  13. void read(int &k)
  14. {
  15. int f=;k=;char c=getchar();
  16. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  17. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  18. k*=f;
  19. }
  20. int lowbit(int x){return x&-x;}
  21. void update(int x,int delta){for(;x<=n;x+=lowbit(x))a[x]+=delta;}
  22. int sum(int x){int ret=;for(;x;x-=lowbit(x))ret+=a[x];return ret;}
  23. void add(int x,int y){e[++tot].too=y;e[tot].pre=last[x];last[x]=tot;}
  24. void dfs(int x,int fa)
  25. {
  26. ans[p[x]]=sum(p[x]-);
  27. update(p[x],);
  28. for(int i=last[x];i;i=e[i].pre)
  29. if(e[i].too!=fa)
  30. dfs(e[i].too,x);
  31. update(p[x],-);
  32. }
  33. int main()
  34. {
  35. read(n);
  36. for(int i=;i<n;i++)read(x),read(y),add(x,y),add(y,x);
  37. for(int i=;i<=n;i++)read(v[i]);
  38. for(int i=;i<=n;i++)p[v[i]]=i;
  39. dfs(,);
  40. for(int i=;i<=n;i++)printf("%d\n",ans[i]);
  41. return ;
  42. }

  bzoj1571: [Usaco2009 Open]滑雪课Ski

    挺显然的一个DP

    f[i][j]表示时间i,能力值为j最多滑几次

    预处理出mind[i]表示能力值为i滑一次雪的最短时间,ke[i][j]表示时间i结束,能力值达到j的课程开始的时间。

    f[i][j]=max(f[i-1][j],f[i-mind[j]][j]+1,f[ke[i][j]][k]]);

    最后一个可以开个数组g[i][j]记录max(f[i][1~j])来优化。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<queue>
  6. #include<algorithm>
  7. #define ll long long
  8. using namespace std;
  9. const int maxn=;
  10. int n,x,y,z,tot,ans,t,s,m[maxn],l[maxn],a[maxn],c[maxn],d[maxn];
  11. int f[maxn][],g[maxn][],mind[maxn],ke[maxn][];
  12. void read(int &k)
  13. {
  14. int f=;k=;char c=getchar();
  15. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  16. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  17. k*=f;
  18. }
  19. int main()
  20. {
  21. read(t);read(s);read(n);
  22. for(int i=;i<=s;i++)
  23. read(m[i]),read(l[i]),read(a[i]),ke[m[i]+l[i]][a[i]]=m[i];
  24. for(int i=;i<=n;i++)read(c[i]),read(d[i]);
  25. for(int i=;i<=;i++)mind[i]=;
  26. for(int i=;i<=;i++)
  27. for(int j=;j<=n;j++)
  28. if(c[j]<=i)mind[i]=min(mind[i],d[j]);
  29. memset(f,-,sizeof(f));
  30. memset(g,-,sizeof(g));
  31. f[][]=g[][]=;
  32. for(int i=;i<=t;i++)
  33. {
  34. for(int j=;j<=;j++)
  35. {
  36. f[i][j]=f[i-][j];
  37. if(i>=mind[j])f[i][j]=max(f[i][j],f[i-mind[j]][j]+);
  38. f[i][j]=max(f[i][j],g[ke[i][j]][j]);
  39. g[i][j]=max(g[i][j-],f[i][j]);
  40. }
  41. }
  42. int ans=;
  43. for(int i=;i<=;i++)ans=max(ans,f[t][i]);
  44. printf("%d\n",ans);
  45. return ;
  46. }

  bzoj1715: [Usaco2006 Dec]Wormholes 虫洞

    spfa判负环。

    傻了,输出NO没过行WA了好几次,输样例的时候看不出来。

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. using namespace std;
  6. struct zs{int dis,pre,too;}e[];
  7. int i,now,n,m,front,rear,x,y,z,tot,T,w;
  8. int h[],last[],dis[],ru[];
  9. bool v[];
  10. void read(int &k)
  11. {
  12. int f=;k=;char c=getchar();
  13. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  14. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  15. k*=f;
  16. }
  17. int spfa(int x)
  18. {
  19. memset(dis,,(n+)<<);memset(v,,sizeof(v));memset(ru,,sizeof(ru));
  20. dis[x]=;front=;rear=;h[]=x;v[x]=;
  21. while(front!=rear)
  22. {
  23. now=h[++front];if(front==)front=-;
  24. for(int i=last[now],to=e[i].too;i;i=e[i].pre,to=e[i].too)
  25. if(dis[to]>dis[now]+e[i].dis)
  26. {
  27. dis[to]=dis[now]+e[i].dis;
  28. if(!v[to])
  29. {
  30. h[++rear]=to;if(rear==)rear=-;
  31. v[to]=;ru[to]++;
  32. if(ru[to]>)return ;
  33. }
  34. }
  35. v[now]=;
  36. }
  37. return ;
  38. }
  39. void add(int x,int y,int z)
  40. {
  41. e[++tot].too=y;e[tot].dis=z;e[tot].pre=last[x];last[x]=tot;
  42. }
  43. int main()
  44. {
  45. read(T);
  46. while(T--)
  47. {
  48. tot=;memset(last,,sizeof(last));
  49. read(n);read(m);read(w);
  50. for(int i=;i<=m;i++)
  51. read(x),read(y),read(z),add(x,y,z),add(y,x,z);
  52. for(int i=;i<=w;i++)
  53. read(x),read(y),read(z),add(x,y,-z);
  54. if(spfa())printf("YES\n");
  55. else printf("NO\n");
  56. }
  57. return ;
  58. }

  bzoj1596: [Usaco2008 Jan]电话网络

    树形DP

    dp[i][0]为i被覆盖,i不建塔

    dp[i][1]为i建塔

    dp[i][2]为i不被覆盖,i不建塔

    一开始inf开太大GG了呜呜

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<queue>
  6. #include<algorithm>
  7. #define ll long long
  8. using namespace std;
  9. const int maxn=,inf=;
  10. struct poi{int too,pre;}e[maxn];
  11. int n,m,x,y,z,tot;
  12. int dp[maxn][],last[maxn];
  13. void read(int &k)
  14. {
  15. int f=;k=;char c=getchar();
  16. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  17. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  18. k*=f;
  19. }
  20. void add(int x,int y){e[++tot].too=y;e[tot].pre=last[x];last[x]=tot;}
  21. void dfs(int x,int fa)
  22. {
  23. dp[x][]=inf;dp[x][]=;dp[x][]=;
  24. int sum=;
  25. for(int i=last[x];i;i=e[i].pre)
  26. if(e[i].too!=fa)
  27. {
  28. dfs(e[i].too,x);
  29. dp[x][]+=min(dp[e[i].too][],min(dp[e[i].too][],dp[e[i].too][]));
  30. dp[x][]+=min(dp[e[i].too][],dp[e[i].too][]);
  31. sum+=min(dp[e[i].too][],dp[e[i].too][]);
  32. }
  33. for(int i=last[x];i;i=e[i].pre)
  34. if(e[i].too!=fa)
  35. dp[x][]=min(dp[x][],dp[e[i].too][]-min(dp[e[i].too][],dp[e[i].too][])+sum);
  36. }
  37. int main()
  38. {
  39. read(n);
  40. for(int i=;i<n;i++)
  41. read(x),read(y),add(x,y),add(y,x);
  42. dfs(,);
  43. printf("%d",min(dp[][],dp[][]));
  44. return ;
  45. }

  bzoj1770: [Usaco2009 Nov]lights 燈

    meet in the middle

    直接用Claris题解啦!

    

    好像还能写高斯消元,那明天就学高斯消元吧嘿嘿嘿   UPD:不学了好难啊

    又又又又又又叕叕叕叕叕叕交成老代码WA了好多次啊淦

    好激心,对着能AC的代码找了大概有1h+找不出错

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<queue>
  6. #include<algorithm>
  7. #include<map>
  8. #define ll long long
  9. using namespace std;
  10. const int maxn=,inf=;
  11. map<ll,int>cnt;
  12. int n,m,x,y,half,ans;
  13. ll f[],state;
  14. void read(int &k)
  15. {
  16. int f=;k=;char c=getchar();
  17. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  18. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  19. k*=f;
  20. }
  21. void dfs1(int x,ll st,int t)
  22. {
  23. if(x==half)
  24. {
  25. int &cntt=cnt[st];
  26. if(!cntt)cntt=t;
  27. else cntt=min(cntt,t);
  28. return;
  29. }
  30. dfs1(x+,st,t);dfs1(x+,st^f[x],t+);
  31. }
  32. void dfs2(int x,ll st,int t)
  33. {
  34. if(x==(n-half))
  35. {
  36. int &cntt=cnt[state^st];
  37. if(cntt)ans=min(ans,cntt+t-);
  38. return;
  39. }
  40. dfs2(x+,st,t);dfs2(x+,st^f[x+half],t+);
  41. }
  42. int main()
  43. {
  44. read(n);read(m);
  45. half=n/;state=(1ll<<n)-;
  46. for(int i=;i<=m;i++)
  47. {
  48. read(x);read(y);
  49. x--;y--;
  50. f[x]|=1ll<<y;
  51. f[y]|=1ll<<x;
  52. }
  53. for(int i=;i<n;i++)f[i]|=1ll<<i;
  54. ans=inf;
  55. dfs1(,,);dfs2(,,);
  56. printf("%d\n",ans);
  57. return ;
  58. }

  bzoj1691: [Usaco2007 Dec]挑剔的美食家

    贪心,用splay维护。把牛和牧草都按新鲜程度从大到小排序,枚举牛,把新鲜程度大于牛要求的都加进splay,找到牛要求的价格-1的后继,加入答案。

    感觉splay的删除操作写的还是有点丑,下次再改改。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #define which(x) (son[fa[x]][1]==x)
  7. #define ll long long
  8. using namespace std;
  9. const int maxn=;
  10. struct poi{int cost,fresh;}a[maxn],b[maxn];
  11. const int extar[]={,-};
  12. int fa[maxn],cnt[maxn],son[maxn][],val[maxn],data[maxn];
  13. int root,x,y,n,m,j,tot,xiugai;
  14. ll ans;
  15. void read(int &k)
  16. {
  17. int f=;k=;char c=getchar();
  18. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  19. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  20. k*=f;
  21. }
  22. bool cmp(poi a,poi b){return a.fresh>b.fresh;}
  23. void rotate(int x)
  24. {
  25. int f=fa[x];
  26. bool k=which(x);
  27. son[f][k]=son[x][!k];son[x][!k]=f;son[fa[f]][which(f)]=x;
  28. if(son[f][k])fa[son[f][k]]=f;fa[x]=fa[f];fa[f]=x;
  29. cnt[x]=cnt[f];
  30. cnt[f]=cnt[son[f][]]+cnt[son[f][]]+val[f];
  31. }
  32. void splay(int x,int g)
  33. {
  34. while(fa[x]!=g)
  35. {
  36. int f=fa[x];
  37. if(fa[f]==g)
  38. {
  39. rotate(x);
  40. break;
  41. }
  42. if(which(x)^which(f))rotate(x);
  43. else rotate(f);
  44. rotate(x);
  45. }
  46. if(!g)root=x;
  47. }
  48. int search(int x,int y)
  49. {
  50. if(data[x]>y&&son[x][])return search(son[x][],y);
  51. if(data[x]<y&&son[x][])return search(son[x][],y);
  52. return x;
  53. }
  54. int ext(int x,int w)
  55. {
  56. int k=search(x,extar[w]);
  57. splay(k,);
  58. return data[k];
  59. }
  60. int succ(int x)
  61. {
  62. int k=search(root,x);
  63. splay(k,);
  64. if(data[k]>x)return data[k];
  65. return ext(son[k][],);
  66. }
  67. void insert(int &x,int w,int f)
  68. {
  69. if(!x)
  70. {
  71. x=++tot;
  72. cnt[x]=val[x]=;
  73. data[x]=w;
  74. fa[x]=f;
  75. xiugai=tot;
  76. return;
  77. }
  78. if(data[x]==w)val[x]++,xiugai=x;
  79. if(data[x]<w)insert(son[x][],w,x);
  80. if(data[x]>w)insert(son[x][],w,x);
  81. cnt[x]++;
  82. }
  83. void del(int w)
  84. {
  85. int k=search(root,w);
  86. splay(k,);
  87. if(data[k]==w)
  88. {
  89. if(val[k]>)val[k]--,cnt[k]--;
  90. else
  91. if(!son[k][])
  92. {
  93. root=son[k][];
  94. fa[root]=fa[k]=son[k][]=cnt[k]=val[k]=data[k]=;
  95. }
  96. else
  97. {
  98. fa[son[k][]]=;ext(son[k][],);
  99. son[root][]=son[k][];
  100. if(son[k][])fa[son[k][]]=root;
  101. cnt[root]+=cnt[son[k][]];
  102. fa[k]=son[k][]=son[k][]=data[k]=val[k]=cnt[k]=;
  103. }
  104. }
  105. }
  106. int main()
  107. {
  108. read(n);read(m);
  109. if(n>m)
  110. {
  111. printf("-1\n");
  112. return ;
  113. }
  114. for(int i=;i<=n;i++)read(a[i].cost),read(a[i].fresh);
  115. for(int i=;i<=m;i++)read(b[i].cost),read(b[i].fresh);
  116. sort(a+,a++n,cmp);sort(b+,b++m,cmp);
  117. j=;
  118. for(int i=;i<=n;i++)
  119. {
  120. for(;b[j].fresh>=a[i].fresh&&j<=m;j++)
  121. {
  122. insert(root,b[j].cost,);
  123. splay(xiugai,);
  124. }
  125. int now=succ(a[i].cost-);
  126. if(now)ans+=now;
  127. else
  128. {
  129. printf("-1\n");
  130. return ;
  131. }
  132. del(now);
  133. }
  134. printf("%lld\n",ans);
  135. return ;
  136. }

  bzoj1668: [Usaco2006 Oct]Cow Pie Treasures 馅饼里的财富

    经典DP

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<queue>
  6. #include<algorithm>
  7. #define ll long long
  8. using namespace std;
  9. const int maxn=;
  10. int n,m,x,y,z,tot;
  11. int f[maxn][maxn],map[maxn][maxn];
  12. void read(int &k)
  13. {
  14. int f=;k=;char c=getchar();
  15. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  16. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  17. k*=f;
  18. }
  19. int main()
  20. {
  21. read(n);read(m);
  22. for(int i=;i<=n;i++)
  23. for(int j=;j<=m;j++)
  24. read(map[i][j]);
  25. memset(f,-0x7f,sizeof(f));
  26. f[][]=;
  27. for(int j=;j<=m;j++)
  28. for(int i=;i<=n;i++)
  29. f[i][j]=max(f[i+][j-],max(f[i][j-],f[i-][j-]))+map[i][j];
  30. printf("%d\n",f[n][m]);
  31. return ;
  32. }

  bzoj1593: [Usaco2008 Feb]Hotel 旅馆

    线段树维护左边,中间,最大值。

    查询时按 左 中 右的顺序查就可以保证最左边了

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<queue>
  6. #include<algorithm>
  7. #include<map>
  8. #define ll long long
  9. using namespace std;
  10. const int maxn=,inf=1e9;
  11. struct poi{int l,r,m,tag;}a[maxn*];
  12. int n,m,x,y,z,tot;
  13. void read(int &k)
  14. {
  15. int f=;k=;char c=getchar();
  16. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  17. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  18. k*=f;
  19. }
  20. void build(int x,int l,int r)
  21. {
  22. a[x].l=a[x].r=a[x].m=r-l+;
  23. if(l==r)return;
  24. int mid=(l+r)>>;
  25. build(x<<,l,mid);build(x<<|,mid+,r);
  26. }
  27. void pushup(int x,int l,int r)
  28. {
  29. int mid=(l+r)>>;
  30. a[x].l=a[x<<].l;a[x].r=a[x<<|].r;
  31. if(a[x<<].l==(mid-l+))a[x].l+=a[x<<|].l;
  32. if(a[x<<|].r==(r-mid))a[x].r+=a[x<<].r;
  33. a[x].m=max(a[x<<].r+a[x<<|].l,max(a[x<<].m,a[x<<|].m));
  34. }
  35. void pushdown(int x,int l,int r)
  36. {
  37. if(a[x].tag==)
  38. {
  39. int mid=(l+r)>>;
  40. a[x<<].l=a[x<<].r=a[x<<].m=mid-l+;a[x<<].tag=;
  41. a[x<<|].l=a[x<<|].r=a[x<<|].m=r-mid;a[x<<|].tag=;
  42. }
  43. if(a[x].tag==)
  44. {
  45. a[x<<].l=a[x<<].r=a[x<<].m=;a[x<<].tag=;
  46. a[x<<|].l=a[x<<|].r=a[x<<|].m=;a[x<<|].tag=;
  47. }
  48. a[x].tag=;
  49. }
  50. void change(int x,int l,int r,int cl,int cr,int delta)
  51. {
  52. if(cl<=l&&r<=cr)
  53. {
  54. a[x].tag=delta;
  55. if(delta==)a[x].l=a[x].r=a[x].m=r-l+;
  56. else a[x].l=a[x].r=a[x].m=;
  57. }
  58. else
  59. {
  60. pushdown(x,l,r);
  61. int mid=(l+r)>>;
  62. if(cl<=mid)change(x<<,l,mid,cl,cr,delta);
  63. if(cr>mid)change(x<<|,mid+,r,cl,cr,delta);
  64. pushup(x,l,r);
  65. }
  66. }
  67. int find(int x,int l,int r,int len)
  68. {
  69. pushdown(x,l,r);
  70. if(l==r)return l;
  71. int mid=(l+r)>>;
  72. if(a[x<<].m>=len)return find(x<<,l,mid,len);
  73. if(a[x<<].r+a[x<<|].l>=len)return mid-a[x<<].r+;
  74. return find(x<<|,mid+,r,len);
  75. }
  76. int main()
  77. {
  78. read(n);read(m);
  79. build(,,n);
  80. for(int i=;i<=m;i++)
  81. {
  82. read(x);
  83. if(x==)
  84. {
  85. read(y);
  86. if(a[x].m>=y)
  87. {
  88. int l=find(,,n,y);
  89. printf("%d\n",l);
  90. change(,,n,l,l+y-,);
  91. }
  92. else printf("0\n");
  93. }
  94. if(x==)
  95. {
  96. read(y);read(z);
  97. change(,,n,y,y+z-,);
  98. }
  99. }
  100. return ;
  101. }

  bzoj1697: [Usaco2007 Feb]Cow Sorting牛排序

    置换群

    两种方法中选更优的一种:(循环节总权值:sum,循环节大小:len,循环节中最小值:minai,数组中最小值:mina)

      ①每个循环节中最小值将其他移回原位。代价:sum+(len-2)*minai

      ②整个数组的最小值移进循环节帮循环节最小值将其他移回原位。代价:sum+(len+1)*mina+minai

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<queue>
  6. #include<algorithm>
  7. #include<vector>
  8. #define ll long long
  9. using namespace std;
  10. const int maxn=;
  11. struct poi{int sum,next;}a[maxn];
  12. int n,m,x,y,z,tot,mina,minai,j,k,ans;
  13. void read(int &k)
  14. {
  15. int f=;k=;char c=getchar();
  16. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  17. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  18. k*=f;
  19. }
  20. bool cmp(poi a,poi b){return a.sum<b.sum;}
  21. int main()
  22. {
  23. read(n);
  24. for(int i=;i<=n;i++)read(a[i].sum),a[i].next=i;
  25. sort(a+,a++n,cmp);
  26. mina=a[].sum;
  27. for(int i=;i<=n;i++)
  28. if(a[i].next!=-)
  29. {
  30. j=a[i].next;minai=a[i].sum;k=;
  31. a[i].next=-;
  32. while(j!=i)
  33. {
  34. k++;
  35. ans+=a[j].sum;
  36. int t=a[j].next;
  37. a[j].next=-;
  38. j=t;
  39. }
  40. ans+=min((k-)*minai,*minai+(k+)*mina);
  41. }
  42. printf("%d\n",ans);
  43. return ;
  44. }

  bzoj1604: [Usaco2008 Open]Cow Neighborhoods 奶牛的邻居

    曼哈顿距离|x1-y1|+|x2-y2|有四种情况

    (x1-y1-(x2-y2))  (x1-y1-(y2-x2))  (y1-x1-(x2-y2))  (y1-x1-(y2-x2))

    那我们陵X=x+y,Y=x-y,那两个点的曼哈顿距离为max(|X1-Y1|,|Y1-Y2|),也就是切比雪夫距离。

    按X排序,保证队头队尾X的差<=c,加入新元素时用set找到(用splay处理重复元素有点麻烦,学习了一波set)前驱后继,如果前驱或后继的y和新加入元素的y差值<=c,就用并查集把新元素和前驱或后继连起来。

    set用法见代码。find找到set中元素,lowerbound找到第一个大于等于它的元素,其实是不一样的,find找不到会返回end()。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<queue>
  6. #include<algorithm>
  7. #include<map>
  8. #include<set>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=;
  12. const ll inf=1e10;
  13. int n,m,x,y,z,tot,ans,ans2,c,now;
  14. int fa[maxn],cnt[maxn];
  15. struct poi{ll x,y;int pos;}a[maxn],hj,qq;
  16. multiset<poi>b;
  17. set<poi>::iterator it;
  18. bool operator<(poi a,poi b){return a.y<b.y;}
  19. void read(int &k)
  20. {
  21. int f=;k=;char c=getchar();
  22. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  23. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  24. k*=f;
  25. }
  26. int gf(int x){return fa[x]==x?x:fa[x]=gf(fa[x]);}
  27. bool cmp(poi a,poi b){return a.x<b.x;}
  28. void link(int x,int y)
  29. {
  30. x=gf(x);y=gf(y);
  31. if(x!=y)
  32. {
  33. fa[x]=y;
  34. ans--;
  35. }
  36. }
  37. int main()
  38. {
  39. read(n);read(c);
  40. for(int i=;i<=n;i++)fa[i]=i;
  41. for(int i=;i<=n;i++)
  42. {
  43. read(x);read(y);ans=n;
  44. a[i].x=x+y;a[i].y=x-y;a[i].pos=i;
  45. }
  46. sort(a+,a++n,cmp);
  47. b.insert((poi){,inf,});b.insert((poi){,-inf,});
  48. now=;b.insert(a[]);
  49. for(int i=;i<=n;i++)
  50. {
  51. while(a[i].x-a[now].x>c)b.erase(b.find(a[now++]));
  52. it=b.lower_bound(a[i]);
  53. hj=*it;qq=*--it;
  54. if(hj.y-a[i].y<=c)link(hj.pos,a[i].pos);
  55. if(a[i].y-qq.y<=c)link(qq.pos,a[i].pos);
  56. b.insert(a[i]);
  57. }
  58. for(int i=;i<=n;i++)cnt[gf(i)]++;
  59. for(int i=;i<=n;i++)ans2=max(ans2,cnt[i]);
  60. printf("%d %d\n",ans,ans2);
  61. return ;
  62. }

  bzoj1589: [Usaco2008 Dec]Trick or Treat on the Farm 采集糖果

    基环树找环+DP

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<queue>
  6. #include<algorithm>
  7. #include<map>
  8. #define ll long long
  9. using namespace std;
  10. const int maxn=,inf=1e9;
  11. int n,m,x,y,z,tot,j,top;
  12. int f[maxn],v[maxn],next[maxn],st[maxn];
  13. void read(int &k)
  14. {
  15. int f=;k=;char c=getchar();
  16. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  17. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  18. k*=f;
  19. }
  20. int main()
  21. {
  22. read(n);
  23. for(int i=;i<=n;i++)read(next[i]);
  24. for(int i=;i<=n;i++)
  25. if(!v[i])
  26. {
  27. int top=;
  28. for(j=i;!v[j];j=next[j])st[++top]=j,v[j]=i;
  29. if(v[j]==i)
  30. {
  31. int cnt=;
  32. for(;st[top-cnt+]!=j;cnt++);
  33. for(int k=;k<=cnt;k++)f[st[top-k+]]=cnt;
  34. top-=cnt;
  35. }
  36. int cnt=;
  37. while(top)f[st[top--]]=f[j]+(++cnt);
  38. }
  39. for(int i=;i<=n;i++)printf("%d\n",f[i]);
  40. return ;
  41. }

  bzoj1574: [Usaco2009 Jan]地震损坏Damage

    一开始看成最少损坏几个了,想了好久QAQ

    最少几个不能去显然把不能去的几个周围一圈全部搞坏就行了,然后再dfs一遍找出一共几个不能回到1点就行了

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<queue>
  6. #include<algorithm>
  7. #define ll long long
  8. using namespace std;
  9. const int maxn=,inf=1e9;
  10. struct poi{int too,pre;}e[maxn];
  11. int n,m,x,y,z,c,ans,tot;
  12. int map[maxn],v[maxn],last[maxn];
  13. void read(int &k)
  14. {
  15. int f=;k=;char c=getchar();
  16. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  17. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  18. k*=f;
  19. }
  20. void add(int x,int y){e[++tot].too=y;e[tot].pre=last[x];last[x]=tot;}
  21. void dfs(int x)
  22. {
  23. ans--;v[x]=;
  24. for(int i=last[x];i;i=e[i].pre)
  25. if(!v[e[i].too])dfs(e[i].too);
  26. }
  27. int main()
  28. {
  29. read(n);read(m);read(c);ans=n;
  30. for(int i=;i<=m;i++)read(x),read(y),add(x,y),add(y,x);
  31. for(int i=;i<=c;i++)
  32. {
  33. read(x);
  34. v[x]=;
  35. for(int j=last[x];j;j=e[j].pre)
  36. v[e[j].too]=;
  37. }
  38. dfs();
  39. printf("%d\n",ans);
  40. return ;
  41. }

  bzoj1707: [Usaco2007 Nov]tanning分配防晒霜

    一开始只会网络流,感觉会TLE,不会写QAQ

    直接拿@willinglive题解啦

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<queue>
  6. #include<algorithm>
  7. #include<map>
  8. #define ll long long
  9. using namespace std;
  10. const int maxn=,inf=1e9;
  11. struct poi{int x,y;}a[maxn];
  12. int n,m,x,y,z,tot,ans,spf[maxn],num[maxn];
  13. void read(int &k)
  14. {
  15. int f=;k=;char c=getchar();
  16. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  17. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  18. k*=f;
  19. }
  20. bool cmp(poi a,poi b){return a.y<b.y;}
  21. int main()
  22. {
  23. read(n);read(m);
  24. for(int i=;i<=n;i++)read(a[i].x),read(a[i].y);
  25. sort(a+,a++n,cmp);
  26. for(int i=;i<=m;i++)read(spf[i]),read(num[i]);
  27. spf[]=inf;
  28. for(int i=;i<=n;i++)
  29. {
  30. int mnj=;
  31. for(int j=;j<=m;j++)
  32. if(num[j])if(a[i].x<=spf[j]&&spf[j]<=a[i].y)if(spf[mnj]>spf[j])mnj=j;
  33. if(mnj)ans++,num[mnj]--;
  34. }
  35. printf("%d\n",ans);
  36. return ;
  37. }

  bzoj1709: [Usaco2007 Oct]Super Paintball超级弹珠

    直接记录。。。左上到右下是x-y+n,右上到左下是x+y-1,注意可能站在对手的位置射....

    没删调试输出交上去WA了一次QAQ

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<queue>
  6. #include<algorithm>
  7. #define ll long long
  8. using namespace std;
  9. const int maxn=,inf=1e9;
  10. int n,k,x,y,z,tot,ans;
  11. int row[maxn],col[maxn],lt[maxn],rt[maxn],map[maxn][maxn];
  12. void read(int &k)
  13. {
  14. int f=;k=;char c=getchar();
  15. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  16. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  17. k*=f;
  18. }
  19. int main()
  20. {
  21. read(n);read(k);
  22. for(int i=;i<=k;i++)
  23. {
  24. read(x);read(y);map[x][y]++;
  25. row[x]++;col[y]++;lt[x-y+n]++;rt[x+y-]++;
  26. }
  27. for(int i=;i<=n;i++)
  28. for(int j=;j<=n;j++)
  29. if(row[i]+col[j]+lt[i-j+n]+rt[i+j-]-*map[i][j]==k)ans++;
  30. printf("%d\n",ans);
  31. return ;
  32. }

  bzoj1706: [usaco2007 Nov]relays 奶牛接力跑

    之前写过题解

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. #define ll long long
  6. using namespace std;
  7. const int maxn=;
  8. struct poi{ll mtx[maxn][maxn];}f,g;
  9. ll n,m,s,t,tot,x,y,z;
  10. int v[];
  11. void read(ll &k)
  12. {
  13. int f=;k=;char c=getchar();
  14. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  15. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  16. k*=f;
  17. }
  18. void floyd(poi &a,poi b)
  19. {
  20. poi c;memset(c.mtx,0x3f,sizeof(c.mtx));
  21. for(int k=;k<=tot;k++)
  22. for(int i=;i<=tot;i++)
  23. for(int j=;j<=tot;j++)
  24. c.mtx[i][j]=min(c.mtx[i][j],a.mtx[i][k]+b.mtx[k][j]);
  25. memcpy(a.mtx,c.mtx,sizeof(c.mtx));
  26. }
  27. void ksm(int n)
  28. {
  29. while(n)
  30. {
  31. if(n&)floyd(g,f);
  32. floyd(f,f);
  33. n>>=;
  34. }
  35. }
  36. int main()
  37. {
  38. read(n);read(m);read(s);read(t);
  39. memset(f.mtx,0x3f,sizeof(f.mtx));
  40. for(int i=;i<=m;i++)
  41. {
  42. read(z);read(x);read(y);
  43. if(!v[x])v[x]=++tot;if(!v[y])v[y]=++tot;
  44. f.mtx[v[x]][v[y]]=min(f.mtx[v[x]][v[y]],z);
  45. f.mtx[v[y]][v[x]]=min(f.mtx[v[y]][v[x]],z);
  46. }
  47. memset(g.mtx,0x3f,sizeof(g.mtx));
  48. for(int i=;i<=tot;i++)g.mtx[i][i]=;
  49. ksm(n);
  50. printf("%lld\n",g.mtx[v[s]][v[t]]);
  51. return ;
  52. }

  bzoj1753: [Usaco2005 qua]Who's in the Middle

    ...直接排序

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<queue>
  6. #include<algorithm>
  7. #include<map>
  8. #define ll long long
  9. using namespace std;
  10. const int maxn=,inf=1e9;
  11. int n,m,x,y,z,tot;
  12. int a[maxn];
  13. void read(int &k)
  14. {
  15. int f=;k=;char c=getchar();
  16. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  17. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  18. k*=f;
  19. }
  20. int main()
  21. {
  22. read(n);
  23. for(int i=;i<=n;i++)read(a[i]);
  24. sort(a+,a++n);
  25. printf("%d\n",a[(n+)>>]);
  26. return ;
  27. }

  bzoj1584: [Usaco2009 Mar]Cleaning Up 打扫卫生

    有趣的DP...不会写(躺。感觉自己思维每次只能碰到正解的一部分,却达不到最关键的点,只想到了不同数个数的平方一定要小于长度,却没有根据这个推出不同数个数不能超过sqrt(n),虽然是显而易见的...(其实感觉跟不确定这题到底是不是DP有关,因为看数据范围就觉得像根号,但是从没见过带根号的DP...

    f[i]=min(f[b[j]]+j*j)(1≤j*j≤n)

    b[j]表示b[j]+1~i的出现次数为j。维护的话记录下每个a[i]最晚出现次数pre[a[i]],如果pre[a[i]]并没有出现在b[j]+1~i也就是pre[a[i]]<=b[j]的话,这一段的不同数个数就要增加(cnt[j]++),如果cnt[j]>j的话就必须从b[j]+1一直向右删,删到第一个在这一段里只出现一次的数,这可以用pre来判断。

    总的时间复杂度O(nsqrt(n))

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. int n,m,x,y,z,tot,k;
  13. int a[maxn],b[maxn],pre[maxn],cnt[maxn];
  14. ll f[maxn];
  15. void read(int &k)
  16. {
  17. int f=;k=;char c=getchar();
  18. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  19. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  20. k*=f;
  21. }
  22. int main()
  23. {
  24. read(n);read(m);
  25. for(int i=;i<=n;i++)read(a[i]);
  26. memset(pre,-,sizeof(pre));
  27. memset(f,0x7f,sizeof(f));
  28. f[]=;
  29. for(int i=;i<=n;i++)
  30. {
  31. for(int j=;j*j<=n;j++)
  32. if(pre[a[i]]<=b[j])
  33. {
  34. cnt[j]++;
  35. if(cnt[j]>j)
  36. {
  37. for(k=b[j]+;k<pre[a[k]];k++);
  38. b[j]=k;cnt[j]--;
  39. }
  40. }
  41. for(int j=;j*j<=n;j++)
  42. f[i]=min(f[i],f[b[j]]+j*j);
  43. pre[a[i]]=i;
  44. }
  45. printf("%lld\n",f[n]);
  46. return ;
  47. }

  bzoj1754: [Usaco2005 qua]Bull Math

    高精度乘法,WA了5次,调了1h,身败名裂QAQ

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. int lena,lenb,lenc;
  13. int a[maxn],b[maxn],c[maxn];
  14. char s1[],s2[];
  15. int main()
  16. {
  17. scanf("%s%s",s1,s2);
  18. lena=strlen(s1);lenb=strlen(s2);
  19. for(int i=;i<lena;i++)a[lena-i]=s1[i]-'';
  20. for(int i=;i<lenb;i++)b[lenb-i]=s2[i]-'';
  21. for(int i=;i<=lena;i++)
  22. {
  23. int x=;
  24. for(int j=;j<=lenb;j++)
  25. {
  26. x=a[i]*b[j]+x+c[i+j-];
  27. c[i+j-]=x%;
  28. x/=;
  29. }
  30. c[i+lenb]=x;
  31. }
  32. lenc=lena+lenb;
  33. while((!c[lenc])&&lenc>)lenc--;
  34. for(int i=lenc;i;i--)printf("%d",c[i]);
  35. printf("\n");
  36. return ;
  37. }

  bzoj1828: [Usaco2010 Mar]balloc 农场分配

    贪心,右端点第一关键字升序,左端点第二关键字降序,一个一个能取就取,正确性自己脑洞一下就知道了

    感觉现在线段树挺熟悉的了,10min敲完 1A

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. struct poi{int min,delta;}a[maxn*];
  13. struct tjm{int x,y;}v[maxn];
  14. int n,m,x,y,z,tot,mn,ans;
  15. void read(int &k)
  16. {
  17. int f=;k=;char c=getchar();
  18. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  19. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  20. k*=f;
  21. }
  22. bool cmp(tjm a,tjm b){return a.y==b.y?a.x>b.x:a.y<b.y;}
  23. void pushup(int x,int l,int r){if(l!=r)a[x].min=min(a[x<<].min,a[x<<|].min);}
  24. void pushdown(int x,int l,int r)
  25. {
  26. if(l==r)return;
  27. a[x<<].delta+=a[x].delta;a[x<<|].delta+=a[x].delta;
  28. a[x<<].min+=a[x].delta;a[x<<|].min+=a[x].delta;
  29. a[x].delta=;
  30. }
  31. void build(int x,int l,int r)
  32. {
  33. if(l==r)read(a[x].min);
  34. else
  35. {
  36. int mid=(l+r)>>;
  37. build(x<<,l,mid);
  38. build(x<<|,mid+,r);
  39. pushup(x,l,r);
  40. }
  41. }
  42. void update(int x,int l,int r,int wl,int wr,int delta)
  43. {
  44. if(wl<=l&&r<=wr)a[x].delta+=delta,a[x].min+=delta;
  45. else
  46. {
  47. pushdown(x,l,r);
  48. int mid=(l+r)>>;
  49. if(wl<=mid)update(x<<,l,mid,wl,wr,delta);
  50. if(wr>mid)update(x<<|,mid+,r,wl,wr,delta);
  51. pushup(x,l,r);
  52. }
  53. }
  54. int query(int x,int l,int r,int wl,int wr)
  55. {
  56. if(wl<=l&&r<=wr)return a[x].min;
  57. else
  58. {
  59. pushdown(x,l,r);
  60. int mid=(l+r)>>,ans=inf;
  61. if(wl<=mid)ans=min(ans,query(x<<,l,mid,wl,wr));
  62. if(wr>mid)ans=min(ans,query(x<<|,mid+,r,wl,wr));
  63. return ans;
  64. }
  65. }
  66. int main()
  67. {
  68. read(n);read(m);
  69. build(,,n);
  70. for(int i=;i<=m;i++)read(v[i].x),read(v[i].y);
  71. sort(v+,v++m,cmp);
  72. for(int i=;i<=m;i++)
  73. {
  74. mn=query(,,n,v[i].x,v[i].y);
  75. if(mn)ans++,update(,,n,v[i].x,v[i].y,-);
  76. }
  77. printf("%d\n",ans);
  78. return ;
  79. }

  bzoj1710: [Usaco2007 Open]Cheappal 廉价回文

    添加和删除一样,然后就是经典DP了。f[l][r]表示把[l,r]改为回文的最小代价,则有:

    f[l][r]=min(f[l+1][r]+cost[s[l]],f[l][r-1]+cost[s[r]];

    if(s[l]==s[r])f[l][r]=min(f[l][r],f[l+1][r-1]);

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. int n,m,x,y,z,tot;
  13. int f[maxn][maxn],cost[maxn];
  14. char s[maxn],ch[];
  15. void read(int &k)
  16. {
  17. int f=;k=;char c=getchar();
  18. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  19. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  20. k*=f;
  21. }
  22. int main()
  23. {
  24. read(n);read(m);
  25. scanf("%s",s+);
  26. for(int i=;i<=n;i++)
  27. {
  28. scanf("%s",ch);read(x);read(y);
  29. cost[(int)ch[]]=min(x,y);
  30. }
  31. for(int i=;i<m;i++)
  32. for(int l=;l<=m-i;l++)
  33. {
  34. f[l][l+i]=min(f[l+][l+i]+cost[(int)s[l]],f[l][l+i-]+cost[(int)s[l+i]]);
  35. if(s[l]==s[l+i])f[l][l+i]=min(f[l][l+i],f[l+][l+i-]);
  36. }
  37. printf("%d\n",f[][m]);
  38. return ;
  39. }

  bzoj1598: [Usaco2008 Mar]牛跑步

    K短路,启发式搜索A*模板。

    f(n)=g(n)+h(n),g为n到起点实际距离,h为n到终点最短距离,所以先跑一遍最短路,从n点开始A*,1进队k次后得到k个答案。

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. #include<queue>
  6. using namespace std;
  7. const int maxn=,inf=1e9;
  8. struct poi{int dis,pos;};
  9. struct zs{int too,sum,pre;}e[maxn],e2[maxn];
  10. priority_queue<poi>q;
  11. bool operator<(poi a,poi b){return a.dis>b.dis;}
  12. int n,m,k,x,y,z,tot;
  13. int last[maxn],last2[maxn],dist[maxn],tim[maxn],ans[maxn];
  14. bool v[maxn];
  15. void read(int &k)
  16. {
  17. int f=;k=;char c=getchar();
  18. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  19. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  20. k*=f;
  21. }
  22. void add1(int x,int y,int z){e[++tot].too=y;e[tot].sum=z;e[tot].pre=last[x];last[x]=tot;}
  23. void add2(int x,int y,int z){e2[++tot].too=y;e2[tot].sum=z;e2[tot].pre=last2[x];last2[x]=tot;}
  24. void spfa()
  25. {
  26. for(int i=;i<=n;i++)dist[i]=inf;
  27. dist[]=;q.push((poi){,});
  28. while(!q.empty())
  29. {
  30. int now=q.top().pos;q.pop();
  31. for(int i=last[now],too=e[i].too;i;i=e[i].pre,too=e[i].too)
  32. if(dist[too]>dist[now]+e[i].sum)
  33. {
  34. dist[too]=dist[now]+e[i].sum;
  35. if(!v[too])
  36. {
  37. v[too]=;
  38. q.push((poi){dist[too],too});
  39. }
  40. }
  41. v[now]=;
  42. }
  43. }
  44. void astar()
  45. {
  46. q.push((poi){dist[n],n});
  47. while(!q.empty())
  48. {
  49. poi top=q.top();int now=top.pos,dis=top.dis;q.pop();
  50. tim[now]++;
  51. if(now==)ans[tim[now]]=dis;
  52. if(tim[now]<=k)
  53. for(int i=last2[now],too=e2[i].too;i;i=e2[i].pre,too=e2[i].too)
  54. q.push((poi){dis-dist[now]+e2[i].sum+dist[too],too});
  55. }
  56. }
  57. int main()
  58. {
  59. read(n);read(m);read(k);
  60. for(int i=;i<=m;i++)
  61. {
  62. read(x);read(y);read(z);
  63. add1(y,x,z);add2(x,y,z);
  64. }
  65. spfa();
  66. astar();
  67. for(int i=;i<=k;i++)
  68. if(ans[i])printf("%d\n",ans[i]);
  69. else printf("-1\n");
  70. return ;
  71. }

  bzoj2060: [Usaco2010 Nov]Visiting Cows 拜访奶牛

    树形DP f[x][1]表示x选  f[x][0]表示x不选

    f[x][1]=sigma(f[son[]][0]);

    f[x][0]=max(sigma(max(f[son[]][0],f[son[]][1]))-max(f[son[i]][0],f[son[i]][1])+f[son[i]][1]);

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. struct poi{int too,pre;}e[maxn];
  13. int n,m,x,y,z,tot;
  14. int f[maxn][],last[maxn];
  15. void read(int &k)
  16. {
  17. int f=;k=;char c=getchar();
  18. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  19. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  20. k*=f;
  21. }
  22. void add(int x,int y){e[++tot].too=y;e[tot].pre=last[x];last[x]=tot;}
  23. void dp(int x,int fa)
  24. {
  25. f[x][]=;int sum=;
  26. for(int i=last[x];i;i=e[i].pre)
  27. if(e[i].too!=fa)
  28. {
  29. dp(e[i].too,x);
  30. f[x][]+=f[e[i].too][];
  31. sum+=max(f[e[i].too][],f[e[i].too][]);
  32. }
  33. for(int i=last[x];i;i=e[i].pre)
  34. if(e[i].too!=fa)f[x][]=max(f[x][],sum-max(f[e[i].too][],f[e[i].too][])+f[e[i].too][]);
  35. }
  36. int main()
  37. {
  38. read(n);
  39. for(int i=;i<n;i++)read(x),read(y),add(x,y),add(y,x);
  40. dp(,);
  41. printf("%d\n",max(f[][],f[][]));
  42. return ;
  43. }

  bzoj1741: [Usaco2005 nov]Asteroids 穿越小行星群

    对于一个小行星(x,y),如果x不打y一定要打,于是x连y做二分图最大匹配就行了,或者可以理解成最小割

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. using namespace std;
  6. struct poi{int too,pre;}e[];
  7. int n,m,x,y,t,tot,ans,num,lin[],last[],v[];
  8. void add(int x,int y){e[++tot].too=y;e[tot].pre=last[x];last[x]=tot;}
  9. void read(int &k)
  10. {
  11. int f=;k=;char c=getchar();
  12. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  13. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  14. k*=f;
  15. }
  16. bool dfs(int x)
  17. {
  18. for(int i=last[x],too=e[i].too;i;i=e[i].pre,too=e[i].too)
  19. if(v[too]!=t)
  20. {
  21. v[too]=t;
  22. if((!lin[too])||dfs(lin[too]))
  23. {
  24. lin[too]=x;
  25. return ;
  26. }
  27. }
  28. return ;
  29. }
  30. int main()
  31. {
  32. read(n);read(m);
  33. for(int i=;i<=m;i++)read(x),read(y),add(x,y);
  34. for(int i=;i<=n;i++)
  35. {
  36. ++t;
  37. if(dfs(i))ans++;
  38. }
  39. printf("%d\n",ans);
  40. }

  bzoj1703: [Usaco2007 Mar]Ranking the Cows 奶牛排名

    传递闭包+bitset优化

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<bitset>
  6. #define ll long long
  7. using namespace std;
  8. const int maxn=,inf=1e9;
  9. int n,m,x,y,ans;
  10. bitset<maxn>a[maxn];
  11. void read(int &k)
  12. {
  13. int f=;k=;char c=getchar();
  14. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  15. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  16. k*=f;
  17. }
  18. int main()
  19. {
  20. read(n);read(m);
  21. for(int i=;i<=m;i++)read(x),read(y),a[x][y]=;
  22. for(int i=;i<=n;i++)
  23. for(int j=;j<=n;j++)
  24. if(a[j][i])a[j]|=a[i];
  25. ans=;
  26. for(int i=;i<=n;i++)
  27. for(int j=i+;j<=n;j++)
  28. if(!(a[i][j]||a[j][i]))ans++;
  29. printf("%d\n",ans);
  30. return ;
  31. }

  bzoj1578: [Usaco2009 Feb]Stock Market 股票市场

    没见过的DP,居然可以用前一天的DP值来当容量(躺(智商太低想不到系列。

    显然某一天卖股票只可能卖一种,也就是之前肯定只买一种来卖,这个自己yy一下就知道了。

    f[i]表示第i天的最大收益,然后用前一天的DP值来做完全背包就行了。至于为什么用前一天的,因为用之前的和用前一天的其实是一样的,相当于之前买的在前一天卖了再买。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. int n,m,x,y,z,tot,d;
  13. int f[],gp[][],g[][];
  14. void read(int &k)
  15. {
  16. int f=;k=;char c=getchar();
  17. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  18. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  19. k*=f;
  20. }
  21. int main()
  22. {
  23. read(n);read(d);read(m);
  24. for(int i=;i<=n;i++)
  25. for(int j=;j<=d;j++)
  26. read(gp[j][i]);
  27. f[]=m;
  28. for(int i=;i<=d;i++)
  29. {
  30. for(int j=;j<=n;j++)
  31. for(int k=gp[i-][j];k<=f[i-];k++)
  32. g[i][k]=max(g[i][k-gp[i-][j]]+gp[i][j]-gp[i-][j],g[i][k]);
  33. f[i]=g[i][f[i-]]+f[i-];
  34. }
  35. printf("%d\n",f[d]);
  36. return ;
  37. }

  bzoj1702: [Usaco2007 Mar]Gold Balanced Lineup 平衡的队列

    转2进制后前缀和,前缀和的每位都减去第一位,如果有两个前缀和 i 和 j 相同的话,那么i+1~j这一段的k种颜色出现次数一样多。哈希之后用map,我的写法怎么这么奇葩233

    很好证明,∵ b1-a1==b2-a2==b3-a3 ∴  b1-b1-(a1-a1)==b2-b1-(a2-a1)==b3-b1-(a3-a1)==0

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. #include<map>
  6. #define ull unsigned long long
  7. using namespace std;
  8. const int maxn=,inf=1e9;
  9. map<ull,int>a;
  10. int n,k,now,ans,x;
  11. int digit[maxn][];
  12. void read(int &k)
  13. {
  14. k=;int f=;char c=getchar();
  15. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  16. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  17. k*=f;
  18. }
  19. int find(int pos)
  20. {
  21. ull sum=;
  22. for(int i=;i<=k;i++)sum=sum*+1ull*digit[pos][i];
  23. if(!a[sum]&&sum)a[sum]=pos;
  24. return a[sum];
  25. }
  26. int main()
  27. {
  28. read(n);read(k);
  29. for(int i=;i<=n;i++)
  30. {
  31. read(x);
  32. int now=;
  33. for(;x;x>>=)digit[i][++now]=x&;
  34. for(int j=;j<=k;j++)digit[i][j]+=digit[i-][j];
  35. }
  36. for(int i=;i<=n;i++)
  37. {
  38. for(int j=;j<=k;j++)digit[i][j]-=digit[i][];
  39. ans=max(ans,i-find(i));
  40. }
  41. printf("%d\n",ans);
  42. }

  bzoj1734: [Usaco2005 feb]Aggressive cows 愤怒的牛

    二分最小值最大化

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. int n,c,x,y,z,tot,l,r,mid;
  13. int a[maxn];
  14. void read(int &k)
  15. {
  16. int f=;k=;char c=getchar();
  17. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  18. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  19. k*=f;
  20. }
  21. bool check()
  22. {
  23. int cnt=,pre=-inf;
  24. for(int i=;i<=n;i++)
  25. {
  26. if(a[i]-pre>=mid)cnt++,pre=a[i];
  27. if(cnt==c)return ;
  28. }
  29. return ;
  30. }
  31. int main()
  32. {
  33. read(n);read(c);
  34. for(int i=;i<=n;i++)read(a[i]);
  35. sort(a+,a++n);
  36. l=;r=1e9;
  37. while(l<r)
  38. {
  39. mid=(l+r+)>>;
  40. if(check())l=mid;
  41. else r=mid-;
  42. }
  43. printf("%d\n",l);
  44. return ;
  45. }

  bzoj1585: [Usaco2009 Mar]Earthquake Damage 2 地震伤害

    最小割。把每个点拆成俩,连起来容量为1,有report的点容量就为inf,原图边按二分图加进去,容量inf。S连1,report的点连T,跑最大流。

    1是不能割的,所以拆点后容量也是inf,查了好久TAT

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. using namespace std;
  6. const int inf=,maxn=;
  7. struct poi{int too,pre,cf;}e[];
  8. int n,m,tot,ans,x,y,z,front,rear,sum,p;
  9. int h[maxn],v[maxn],last[maxn],dis[maxn],cur[maxn];
  10. void read(int &k)
  11. {
  12. int f=;k=;char c=getchar();
  13. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  14. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  15. k*=f;
  16. }
  17. void add(int x,int y,int z)
  18. {
  19. e[++tot].too=y;e[tot].cf=z;e[tot].pre=last[x];last[x]=tot;
  20. e[++tot].too=x;e[tot].pre=last[y];last[y]=tot;
  21. }
  22. bool bfs()
  23. {
  24. for(int i=;i<=sum;i++)v[i]=,dis[i]=-;
  25. dis[]=;v[]=;h[]=;front=;rear=;
  26. while(front!=rear)
  27. {
  28. int now=h[++front];if(front==maxn)front=-;
  29. for(int i=last[now];i;i=e[i].pre)
  30. {
  31. int too=e[i].too;
  32. if((!v[too])&&e[i].cf)
  33. {
  34. dis[too]=dis[now]+;if(too==sum)return ;
  35. v[too]=;h[++rear]=too;if(rear==maxn)rear=-;
  36. }
  37. }
  38. }
  39. return ;
  40. }
  41. int dfs(int x,int f)
  42. {
  43. int flow=,tmp;
  44. if(x==sum)return f;
  45. for(int &i=cur[x];i;i=e[i].pre)
  46. {
  47. int too=e[i].too;
  48. if(dis[too]==dis[x]+&&e[i].cf)
  49. {
  50. tmp=dfs(too,min(f-flow,e[i].cf));
  51. e[i].cf-=tmp;e[i^].cf+=tmp;flow+=tmp;
  52. if(f==flow)return f;
  53. }
  54. }
  55. return flow;
  56. }
  57. void dinic()
  58. {
  59. while(bfs())
  60. {
  61. for(int i=;i<=sum;i++)cur[i]=last[i];
  62. ans+=dfs(,inf);
  63. }
  64. }
  65. int main()
  66. {
  67. tot=;
  68. read(p);read(m);read(n);sum=p*+;
  69. add(,,inf);add(,+p,inf);
  70. for(int i=;i<=p;i++)add(i,i+p,);
  71. for(int i=;i<=m;i++)
  72. read(x),read(y),add(x+p,y,inf),add(y+p,x,inf);
  73. for(int i=;i<=n;i++)
  74. read(x),add(x,x+p,inf),add(x+p,sum,inf);
  75. dinic();
  76. printf("%d\n",ans);
  77. return ;
  78. }

----------------------------------------BZOJ 100题纪念----------------------------------------  

  bzoj1704: [Usaco2007 Mar]Face The Right Way 自动转身机

    O(n)枚举k,O(n)扫一遍判断。从左到右,遇见反着的就转过来,前面的保证已经转好了就不要再动了,一直往后扫就行。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. int n,m,x,y,z,tot,ansk,ans,tim,now;
  13. int a[maxn],v[maxn];
  14. char ch[];
  15. void read(int &k)
  16. {
  17. int f=;k=;char c=getchar();
  18. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  19. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  20. k*=f;
  21. }
  22. int main()
  23. {
  24. read(n);
  25. for(int i=;i<=n;i++)
  26. {
  27. scanf("%s",ch);
  28. if(ch[]=='B')a[i]=;
  29. }
  30. ans=inf;
  31. for(int i=;i<=n;i++)
  32. {
  33. tim=;now=;
  34. for(int j=;j<=n-i+;j++)
  35. {
  36. if(v[j]==i)now^=;
  37. if(a[j]^now)tim++,now^=,v[j+i]=i;
  38. }
  39. bool flag=;
  40. for(int j=n-i+;j<=n;j++)
  41. {
  42. if(v[j]==i)now^=;
  43. if(a[j]^now)
  44. {
  45. flag=;
  46. break;
  47. }
  48. }
  49. if(!flag)
  50. if(tim<ans)ans=tim,ansk=i;
  51. }
  52. printf("%d %d\n",ansk,ans);
  53. return ;
  54. }

  bzoj2199: [Usaco2011 Jan]奶牛议会

    网上题解都不tarjan缩点的。。。一缩就跑到#26了

    因为是求所有解中的,不能拓扑后倒序了,只能一个议案一个议案地枚举,判断Y和N是否可以,如果Y和N都行就是?了。

    今天发现自己写了两年的tarjan一直是错的,怎么还能过那么多题QAQ

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. using namespace std;
  6. const int maxn=;
  7. struct poi{int x,too,pre;}e[maxn],e2[maxn];
  8. int n,m,t,tot,tot2,tott,top,color;
  9. int dfn[maxn],low[maxn],col[maxn],last[maxn],last2[maxn],v[maxn],st[maxn],lack[maxn];
  10. char ans[maxn];
  11. void read(int &k)
  12. {
  13. int f=;k=;char c=getchar();
  14. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  15. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  16. k*=f;
  17. }
  18. int readd()
  19. {
  20. int x;read(x);char c=getchar();
  21. while(c!='Y'&&c!='N')c=getchar();
  22. if(c=='Y')return (x<<)^;
  23. return x<<;
  24. }
  25. void add(int x,int y){e[++tot].too=y;e[tot].x=x;e[tot].pre=last[x];last[x]=tot;}
  26. void add2(int x,int y){e2[++tot2].too=y;e2[tot2].x=x;e2[tot2].pre=last2[x];last2[x]=tot2;}
  27. void dfs(int x)
  28. {
  29. v[x]=t;
  30. for(int i=last2[x];i;i=e2[i].pre)
  31. if(v[e2[i].too]!=t)dfs(e2[i].too);
  32. }
  33. bool check(int x)
  34. {
  35. t++;dfs(x);
  36. for(int i=;i<=n;i++)
  37. if(v[col[(i<<)^]]==t&&v[col[i<<]]==t)return ;
  38. return ;
  39. }
  40. void tarjan(int x)
  41. {
  42. dfn[x]=low[x]=++tott;st[++top]=x;lack[x]=top;
  43. for(int i=last[x];i;i=e[i].pre)
  44. if(!dfn[e[i].too])tarjan(e[i].too),low[x]=min(low[x],low[e[i].too]);
  45. else if(!col[e[i].too])low[x]=min(low[x],dfn[e[i].too]);
  46. if(dfn[x]==low[x])
  47. {
  48. color++;
  49. for(;top>=lack[x];top--)col[st[top]]=color;
  50. }
  51. }
  52. void dfss(int x)
  53. {
  54. v[x]=;
  55. for(int i=last[x];i;i=e[i].pre)
  56. if(!v[e[i].too])dfss(e[i].too);
  57. }
  58. int main()
  59. {
  60. read(n);read(m);
  61. for(int i=;i<=m;i++)
  62. {
  63. int x=readd(),y=readd();
  64. add(x^,y);add(y^,x);
  65. }
  66. for(int i=;i<=((n<<)^);i++)if(!dfn[i])tarjan(i);
  67. for(int i=;i<=tot;i++)
  68. if(col[e[i].x]!=col[e[i].too])add2(col[e[i].x],col[e[i].too]);
  69. for(int i=;i<=n;i++)
  70. {
  71. if(col[(i<<)^]==col[i<<]){puts("IMPOSSIBLE");return ;}
  72. int x=check(col[(i<<)^]),y=check(col[i<<]);
  73. if(!(x||y)){puts("IMPOSSIBLE");return ;}
  74. else if(x&&y)ans[i]='?';
  75. else if(x)ans[i]='Y';
  76. else if(y)ans[i]='N';
  77. }
  78. for(int i=;i<=n;i++)putchar(ans[i]);
  79. }

  bzoj1718: [Usaco2006 Jan] Redundant Paths 分离的路径

    边双连通分量缩点后求出叶子数,(leaf+1)/2为答案,易证,自己脑补

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. struct poi{int x,too,pre;}e[maxn],e2[maxn];
  13. int n,m,x,y,z,tot,tot2,leaf,tott,top,color;
  14. int col[maxn],dfn[maxn],low[maxn],st[maxn],lack[maxn],last[maxn],chu[maxn],last2[maxn],v[maxn];
  15. void read(int &k)
  16. {
  17. int f=;k=;char c=getchar();
  18. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  19. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  20. k*=f;
  21. }
  22. void add(int x,int y){e[++tot].x=x;e[tot].too=y;e[tot].pre=last[x];last[x]=tot;}
  23. void add2(int x,int y){e2[++tot2].x=x;e2[tot2].too=y;e2[tot2].pre=last2[x];last2[x]=tot2;}
  24. void tarjan(int x,int fa)
  25. {
  26. dfn[x]=low[x]=++tott;st[++top]=x;lack[x]=top;
  27. for(int i=last[x],too=e[i].too;i;i=e[i].pre,too=e[i].too)
  28. if(too!=fa)
  29. {
  30. if(!dfn[too])tarjan(too,x),low[x]=min(low[x],low[too]);
  31. else if(!col[too])low[x]=min(low[x],dfn[too]);
  32. }
  33. if(dfn[x]==low[x])for(color++;top>=lack[x];top--)col[st[top]]=color,add2(color,st[top]);
  34. }
  35. int main()
  36. {
  37. read(n);read(m);
  38. for(int i=;i<=m;i++)read(x),read(y),add(x,y),add(y,x);
  39. for(int i=;i<=n;i++)if(!dfn[i])tarjan(i,);
  40. for(int k=;k<=color;k++)
  41. for(int j=last2[k];j;j=e2[j].pre)
  42. for(int i=last[e2[j].too];i;i=e[i].pre)
  43. if(v[col[e[i].too]]!=k&&(col[e[i].too]!=k))chu[k]++,v[col[e[i].too]]=k;
  44. for(int i=;i<=color;i++)if(chu[i]==)leaf++;
  45. printf("%d\n",(leaf+)/);
  46. return ;
  47. }

  bzoj1700: [Usaco2007 Jan]Problem Solving 解题

    DP。f[i][j]表示解决i到j道题的最少天数。

    如果某天付完尾款还能在付首付就有 f[j][i]=min(f[k][j-1]+1)

    不然就  f[j][i]=min(f[k][j-1]+2)

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. int n,m,x,y,z,tot;
  13. int f[maxn][maxn],suma[maxn],sumb[maxn];
  14. void read(int &k)
  15. {
  16. int f=;k=;char c=getchar();
  17. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  18. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  19. k*=f;
  20. }
  21. int main()
  22. {
  23. read(m);read(n);
  24. for(int i=;i<=n;i++)read(suma[i]),read(sumb[i]);
  25. for(int i=;i<=n;i++)suma[i]+=suma[i-],sumb[i]+=sumb[i-];
  26. memset(f,0x3f,sizeof(f));f[][]=;
  27. for(int i=;i<=n;i++)
  28. for(int j=;j<=i;j++)
  29. for(int k=;k<j;k++)
  30. {
  31. if(m>=(sumb[j-]-sumb[k-])&&m>=(suma[i]-suma[j-])&&m>=(sumb[i]-sumb[j-]))
  32. f[j][i]=min(f[j][i],f[k][j-]+);
  33. if(m>=(sumb[j-]-sumb[k-]+suma[i]-suma[j-])&&m>=(sumb[i]-sumb[j-]))
  34. f[j][i]=min(f[j][i],f[k][j-]+);
  35. }
  36. int ans=inf;
  37. for(int i=;i<=n;i++)ans=min(ans,f[i][n]);
  38. printf("%d\n",ans);
  39. return ;
  40. }

  bzoj1755: [Usaco2005 qua]Bank Interest

    。。。。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. double r,m,y;
  13. void read(double &k)
  14. {
  15. int f=;k=;char c=getchar();
  16. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  17. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  18. k*=f;
  19. }
  20. int main()
  21. {
  22. read(r);read(m);read(y);
  23. for(int i=;i<=y;i++)
  24. m=m*(+r/);
  25. printf("%d\n",(int)floor(m));
  26. return ;
  27. }

  bzoj1731: [Usaco2005 dec]Layout 排队布局

    差分约束系统。

    求最大值的话先化成x-y<=c的形式(c为常数),y往x连边权值为c跑最短路。

    求最小值的话先化成x-y>=c的形式(c为常数),y往x连边权值为c跑最长路。

    小于或大于要化成小于等于或大于等于

    负环则无解。dist[n]==inf说明对n无限制。

    理解:x-y<=c化成x<=c+y的形式,类似最短路中的松弛操作(dist[too]>dist[now]+e[i].dis),最长路同理。最短路为最大值是因为同小取小,最长路最小值是因为同大取大。

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. using namespace std;
  6. const int maxn=,inf=1e9;
  7. struct poi{int too,pre,sum;}e[maxn];
  8. int n,ml,md,x,y,z,front,rear,tot;
  9. int dist[maxn],h[maxn],v[maxn],last[maxn],tim[maxn];
  10. bool flag;
  11. void read(int &k)
  12. {
  13. int f=;k=;char c=getchar();
  14. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  15. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  16. k*=f;
  17. }
  18. void add(int x,int y,int z){e[++tot].too=y;e[tot].sum=z;e[tot].pre=last[x];last[x]=tot;}
  19. void spfa()
  20. {
  21. for(int i=;i<=n;i++)dist[i]=inf;
  22. dist[]=;v[]=;front=rear=;h[++rear]=;
  23. while(front!=rear)
  24. {
  25. int now=h[++front];if(front==maxn)front=-;
  26. for(int i=last[now],too=e[i].too;i;i=e[i].pre,too=e[i].too)
  27. if(dist[too]>dist[now]+e[i].sum)
  28. {
  29. dist[too]=dist[now]+e[i].sum;
  30. if(!v[too])
  31. {
  32. if(tim[too]>){printf("-1");flag=;return;}
  33. tim[too]++;v[too]=;h[++rear]=too;
  34. if(rear==maxn)rear=-;
  35. }
  36. }
  37. v[now]=;
  38. }
  39. }
  40. int main()
  41. {
  42. read(n);read(ml);read(md);
  43. for(int i=;i<=n;i++)add(i,i-,);
  44. for(int i=;i<=ml;i++)read(x),read(y),read(z),add(x,y,z);
  45. for(int i=;i<=md;i++)read(x),read(y),read(z),add(y,x,-z);
  46. spfa();
  47. if(flag)return ;
  48. if(dist[n]==inf)printf("-2");
  49. else printf("%d\n",dist[n]);
  50. return ;
  51. }

  bzoj1705: [Usaco2007 Nov]Telephone Wire 架设电话线

    f[i][j]前 i 个柱子,第 i 个高度为 j 的最小代价

    f[i][j] = f[i-1][k] + c*(j-k) + (h[i]-j)^2

    f[i][j] = f[i-1][k] - c*k  + c*j + h[i]^2 - 2*h[i]*j + j^2;

    可以发现k和j无关,所以可以把时间复杂度降低到O(n*100)

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=;
  12. int n,c,x,y,z,mn,ans,tot;
  13. int h[maxn],f[maxn][];
  14. void read(int &k)
  15. {
  16. int f=;k=;char c=getchar();
  17. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  18. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  19. k*=f;
  20. }
  21. int main()
  22. {
  23. read(n);read(c);
  24. for(int i=;i<=n;i++)read(h[i]);
  25. memset(f,0x7f,sizeof(f));
  26. for(int i=;i<=;i++)f[][i]=(h[]-i)*(h[]-i);
  27. for(int i=;i<=n;i++)
  28. {
  29. mn=inf;
  30. for(int j=h[i-];j<max(h[i-],h[i]);j++)mn=min(mn,f[i-][j]-c*j);
  31. for(int j=max(h[i-],h[i]);j<=;j++)
  32. {
  33. mn=min(mn,f[i-][j]-c*j);
  34. f[i][j]=min(f[i][j],mn-*h[i]*j+j*j+c*j+h[i]*h[i]);
  35. }
  36. mn=inf;
  37. for(int j=;j>=h[i];j--)
  38. {
  39. if(j>=h[i-])mn=min(mn,f[i-][j]+c*j);
  40. f[i][j]=min(f[i][j],mn-*h[i]*j+j*j-c*j+h[i]*h[i]);
  41. }
  42. }
  43. ans=inf;
  44. for(int i=;i<=;i++)ans=min(ans,f[n][i]);
  45. printf("%d\n",ans);
  46. return ;
  47. }

  bzoj1575: [Usaco2009 Jan]气象牛Baric

    f[i][j]前 i 个数据,选了 j 个的最小误差

    预处理出st[i] , mid[i][j] , ed[i]表示 i 为开头的误差,选 i 和 j 中间的误差,i 为结尾的误差。

    if(j==1)f[i][j] = st[i];

    else f[i][j] = f[k][j-1] + mid[k][i];

    最后找最小值的时候再把ed[i]加上就行。

    一开始没在数据最小前提下找最小误差WA了两次好气啊

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. #define ll long long
  6. using namespace std;
  7. const int maxn=,inf=1e9;
  8. int n,e;
  9. ll f[maxn][maxn],ans2;
  10. int st[maxn],mid[maxn][maxn],ed[maxn],a[maxn],ans;
  11. void read(int &k)
  12. {
  13. int f=;k=;char c=getchar();
  14. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  15. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  16. k*=f;
  17. }
  18. int main()
  19. {
  20. read(n);read(e);
  21. for(int i=;i<=n;i++)read(a[i]);
  22. for(int i=;i<=n;i++)
  23. {
  24. for(int j=;j<i;j++)st[i]+=*abs(a[i]-a[j]);
  25. for(int j=i+;j<=n;j++)
  26. for(int k=i+;k<j;k++)
  27. mid[i][j]+=abs(*a[k]-a[i]-a[j]);
  28. for(int j=i+;j<=n;j++)ed[i]+=*abs(a[i]-a[j]);
  29. }
  30. memset(f,,sizeof(f));f[][]=;
  31. for(int i=;i<=n;i++)
  32. for(int j=;j<=i;j++)
  33. if(j==)f[i][j]=st[i];
  34. else for(int k=;k<i;k++)f[i][j]=min(f[i][j],f[k][j-]+mid[k][i]);
  35. ans=ans2=inf;
  36. for(int i=;i<=n;i++)
  37. for(int j=;j<=n;j++)
  38. if(f[j][i]+ed[j]<=e)
  39. if(ans>=i)ans=i,ans2=min(ans2,f[j][i]+ed[j]);
  40. printf("%d %lld\n",ans,ans2);
  41. }

  bzoj1783: [Usaco2010 Jan]Taking Turns

    博弈论DP...

    f[i]表示先手取i,先手能取得的最大收益。g[i]表示先手取i,后手能获得的最大收益。

    后手显然每次取之前先手能取的最大收益,因为先手取完变后手。

    因为先手是之前的后手,后手是之前的先手,所以先手之前取什么取决于后手,那么先手就只能取后手取的maxi的后手最大值+a[i]。

    g[i] = f[maxi];

    f[i] = g[maxi] + a[i];

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. int n,m,x,y,z,tot,maxi;
  13. int a[maxn];
  14. ll f[maxn],g[maxn];
  15. void read(int &k)
  16. {
  17. int f=;k=;char c=getchar();
  18. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  19. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  20. k*=f;
  21. }
  22. int main()
  23. {
  24. read(n);
  25. for(int i=;i<=n;i++)read(a[i]);
  26. maxi=n+;
  27. for(int i=n;i;i--)
  28. {
  29. g[i]=f[maxi];
  30. f[i]=g[maxi]+a[i];
  31. if(f[i]>=f[maxi])maxi=i;
  32. }
  33. printf("%lld %lld\n",f[maxi],g[maxi]);
  34. return ;
  35. }

    UPD:还有一种比较妙的做法是,维护X和Y分别表示当前的先手的最大收益和当前的后手的最大收益,实际上先手已经选过了,现在排到后手选,若是后手选了a[i]能大于等于当前的先手,也就是先手能找到一个更大的收益,那么就选,并且后手变先手。

    用DP更好理解。f[i][0]表示先手,f[i][1]表示后手。两人都不选,f[i][0]=f[i+1][0],f[i][1]=f[i+1][1]。但是上次的后手可以变成这次的先手if(f[i+1][1]+a[i]>=f[i][0])f[i][0]=f[i+1][1]+a[i],同时上次先手变这次后手f[i][1]=f[i+1][0];

    注意由于是倒推,应该找个先手的最大值,若后手取一个数没有比当前先手大而变成先手的话,显然先手并不会这么笨,还是取之前那个好

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. int n,a[maxn];
  13. ll x,y;
  14. void read(int &k)
  15. {
  16. int f=;k=;char c=getchar();
  17. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  18. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  19. k*=f;
  20. }
  21. int main()
  22. {
  23. read(n);
  24. for(int i=;i<=n;i++)read(a[i]);
  25. for(int i=n;i;i--)if(y+a[i]>=x)swap(x,y),x+=a[i];
  26. printf("%lld %lld\n",x,y);
  27. return ;
  28. }

  bzoj1774: [Usaco2009 Dec]Toll 过路费

    floyd中间点按点权从小到大枚举,那i->k->j这条路径上点权最大的一定是 i j k 三者之一。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. struct poi{ll c,pos;}a[maxn];
  13. ll n,m,K,x,y,z;
  14. ll f[maxn][maxn],g[maxn][maxn],cc[maxn];
  15. void read(ll &k)
  16. {
  17. int f=;k=;char c=getchar();
  18. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  19. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  20. k*=f;
  21. }
  22. bool cmp(poi a,poi b){return a.c<b.c;}
  23. int main()
  24. {
  25. read(n);read(m);read(K);
  26. for(int i=;i<=n;i++)read(a[i].c),a[i].pos=i,cc[i]=a[i].c;
  27. sort(a+,a++n,cmp);
  28. memset(f,,sizeof(f));memset(g,,sizeof(g));
  29. for(int i=;i<=m;i++)read(x),read(y),read(z),g[y][x]=g[x][y]=min(z,g[x][y]);
  30. for(int i=;i<=n;i++)g[i][i]=;
  31. for(int l=;l<=n;l++)
  32. {
  33. ll k=a[l].pos,c=a[l].c;
  34. for(int i=;i<=n;i++)
  35. for(int j=;j<=n;j++)
  36. {
  37. g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
  38. f[i][j]=min(f[i][j],g[i][k]+g[k][j]+max(c,max(cc[i],cc[j])));
  39. }
  40. }
  41. for(int i=;i<=K;i++)
  42. {
  43. read(x);read(y);
  44. printf("%lld\n",f[x][y]);
  45. }
  46. return ;
  47. }

  bzoj1590: [Usaco2008 Dec]Secret Message 秘密信息

    字典树记录一下就行。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. int n,m,x,y,z,tot;
  13. int next[maxn][],a[maxn],son[maxn],cnt[maxn];
  14. void read(int &k)
  15. {
  16. int f=;k=;char c=getchar();
  17. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  18. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  19. k*=f;
  20. }
  21. void insert(int len)
  22. {
  23. int now=;
  24. for(int i=;i<=len;i++)
  25. {
  26. if(!next[now][a[i]])next[now][a[i]]=++tot;
  27. now=next[now][a[i]];
  28. son[now]++;
  29. if(i==len)cnt[now]++;
  30. }
  31. }
  32. int find(int len)
  33. {
  34. int now=,sum=;
  35. for(int i=;i<=len;i++)
  36. {
  37. if(!next[now][a[i]])break;
  38. now=next[now][a[i]];
  39. if(i==len)sum+=son[now];
  40. else sum+=cnt[now];
  41. }
  42. return sum;
  43. }
  44. int main()
  45. {
  46. tot=;
  47. read(n);read(m);
  48. for(int i=;i<=n;i++)
  49. {
  50. read(x);
  51. for(int j=;j<=x;j++)
  52. read(a[j]);
  53. insert(x);
  54. }
  55. for(int i=;i<=m;i++)
  56. {
  57. read(x);
  58. for(int j=;j<=x;j++)
  59. read(a[j]);
  60. printf("%d\n",find(x));
  61. }
  62. return ;
  63. }

  bzoj1577: [Usaco2009 Feb]庙会捷运Fair Shuttle  

    贪心,能加就加,不能加踢出去最晚下车的。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. struct zs{int y,c,pre;}e[maxn];
  13. struct poi{int y,c;};
  14. priority_queue<poi>q;
  15. bool operator<(poi a,poi b){return a.y<b.y;}
  16. int n,c,x,y,z,k,tot,ans,people;
  17. int last[maxn],xiache[maxn];
  18. void read(int &k)
  19. {
  20. int f=;k=;char c=getchar();
  21. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  22. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  23. k*=f;
  24. }
  25. void add(int x,int y,int z){e[++tot].y=y;e[tot].c=z;e[tot].pre=last[x];last[x]=tot;}
  26. int main()
  27. {
  28. read(k);read(n);read(c);
  29. for(int i=;i<=k;i++)
  30. {
  31. read(x);read(y);read(z);
  32. if(x==y)ans+=z;
  33. else add(x,y,z);
  34. }
  35. for(int i=;i<=n;i++)
  36. {
  37. for(int j=last[i];j;j=e[j].pre)q.push((poi){e[j].y,e[j].c}),people+=e[j].c,xiache[e[j].y]+=e[j].c;
  38. ans+=xiache[i];people-=xiache[i];
  39. while(people>c)
  40. {
  41. poi now=q.top();
  42. people-=now.c;xiache[now.y]-=now.c;q.pop();
  43. if(people<c)q.push((poi){now.y,c-people}),xiache[now.y]+=c-people,people=c;
  44. }
  45. }
  46. printf("%d\n",ans);
  47. return ;
  48. }

  bzoj1663: [Usaco2006 Open]赶集

    按时间排序后DP f[i] = max ( f[i] , f[j]+1 ) t[j] + dis[j][i] <= t[i]

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. struct poi{int t,pos;}a[maxn];
  13. int n,m,x,y,z,tot,ans;
  14. int f[maxn],dis[maxn][maxn];
  15. void read(int &k)
  16. {
  17. int f=;k=;char c=getchar();
  18. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  19. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  20. k*=f;
  21. }
  22. bool cmp(poi a,poi b){return a.t<b.t;}
  23. int main()
  24. {
  25. read(n);
  26. for(int i=;i<=n;i++)read(a[i].t),a[i].pos=i;
  27. sort(a+,a++n,cmp);
  28. for(int i=;i<=n;i++)for(int j=;j<=n;j++)read(dis[i][j]);
  29. for(int i=;i<=n;i++)dis[][i]=dis[][i];
  30. for(int i=;i<=n;i++)
  31. {
  32. for(int j=;j<i;j++)
  33. if(a[j].t+dis[a[j].pos][a[i].pos]<=a[i].t)
  34. {
  35. f[i]=max(f[i],f[j]+);
  36. ans=max(ans,f[i]);
  37. }
  38. }
  39. printf("%d\n",ans);
  40. return ;
  41. }

  bzoj1775: [Usaco2009 Dec]Vidgame 电视游戏问题

    自己瞎写了个DP居然过了...

    f[i][j]表示前 i 个平台,预算为 j 的最大收益

    f[i][j] = max( f[i][j] , max( f[i][k-gp[i]]+pv[j] , f[i-1][k-gp[i]]+pv[j] ) );

    算 i 时 k 循环范围是  v-p[i]~gp[i] ,最后令f[i][k]=f[i][k-p[i]],相当于强制买了平台。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. int n,m,x,y,z,tot,v;
  13. int f[][],p[maxn],g[maxn],gp[maxn],pv[maxn],ans;
  14. void read(int &k)
  15. {
  16. int f=;k=;char c=getchar();
  17. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  18. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  19. k*=f;
  20. }
  21. int main()
  22. {
  23. read(n);read(v);
  24. for(int i=;i<=n;i++)
  25. {
  26. read(p[i]);read(g[i]);
  27. for(int j=;j<=g[i];j++)
  28. {
  29. read(gp[j]);read(pv[j]);
  30. for(int k=v-p[i];k>=gp[j];k--)
  31. f[i][k]=max(f[i][k],max(f[i][k-gp[j]]+pv[j],f[i-][k-gp[j]]+pv[j]));
  32. }
  33. for(int k=v;k>=p[i];k--)f[i][k]=max(f[i-][k],f[i][k-p[i]]);
  34. for(int k=p[i]-;k>=;k--)f[i][k]=f[i-][k];
  35. }
  36. for(int i=;i<=v;i++)ans=max(ans,f[n][v]);
  37. printf("%d\n",ans);
  38. return ;
  39. }

  bzoj1583: [Usaco2009 Mar]Moon Mooing 哞哞叫

    两个公式都是递增的,那么搞一个队列,记录下两个公式分别遍历到哪里,比较两个公式遍历到的元素再算一次公式的大小,把小的一个加入队列并把指针后移一位,这样可以保证一直最小。

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. #define ll long long
  6. using namespace std;
  7. const int maxn=;
  8. ll n,c,num[][],now1,now2,ans[maxn],r;
  9. void read(ll &k)
  10. {
  11. k=;int f=;char c=getchar();
  12. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  13. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  14. k*=f;
  15. }
  16. int main()
  17. {
  18. read(c);read(n);
  19. for(int i=;i<=;i++)
  20. for(int j=;j<=;j++)
  21. read(num[i][j]);
  22. ans[]=c;int l1=,l2=;r=;
  23. now1=num[][]*c/num[][]+num[][];
  24. now2=num[][]*c/num[][]+num[][];
  25. while(r<n)
  26. {
  27. if(now1<now2)
  28. {
  29. if(now1!=ans[r])ans[++r]=now1;
  30. now1=ans[++l1]*num[][]/num[][]+num[][];
  31. }
  32. else
  33. {
  34. if(now2!=ans[r])ans[++r]=now2;
  35. now2=ans[++l2]*num[][]/num[][]+num[][];
  36. }
  37. }
  38. printf("%lld\n",ans[n]);
  39. }

  bzoj1716: [Usaco2006 Dec]The Fewest Coins 找零钱

    对John做多重背包,店家做无限(完全?)背包,如果John给的钱超过n*vmax,那至少给了(n+1)个硬币,根据抽屉原理必有一种硬币有两颗,所以拿回来就行。。。网上题解说的vmax*vmax我不怎么懂QAQ

    涨姿势,原来多重背包还能二进制优化O_O

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=;
  12. struct poi{int c,v;}a[maxn];
  13. int n,m,x,y,z,tot,t,N,t1,t2,vmax,ans,inf;
  14. int f[maxn],g[maxn],v[maxn],c[maxn];
  15. void read(int &k)
  16. {
  17. int f=;k=;char c=getchar();
  18. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  19. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  20. k*=f;
  21. }
  22. bool cmp(poi a,poi b){return a.v<b.v;}
  23. int main()
  24. {
  25. read(n);read(t);
  26. for(int i=;i<=n;i++)read(v[i]),vmax=max(vmax,v[i]);
  27. for(int i=;i<=n;i++)
  28. {
  29. read(c[i]);
  30. for(int j=;j<=c[i];j<<=)a[++N].c=j,a[N].v=v[i]*j,c[i]-=j;
  31. if(c[i])a[++N].c=c[i],a[N].v=c[i]*v[i];
  32. }
  33. sort(a+,a++N,cmp);
  34. t1=t+n*vmax;t2=n*vmax;
  35. while(N&&a[N].v>t1)N--;
  36. memset(f,,(t1+)<<);f[]=;inf=f[];
  37. for(int i=;i<=N;i++)
  38. {
  39. for(int j=t1;j>=a[i].v;j--)
  40. f[j]=min(f[j],f[j-a[i].v]+a[i].c);
  41. }
  42. memset(g,,(t2+)<<);g[]=;
  43. for(int i=;i<=n;i++)
  44. {
  45. for(int j=v[i];j<=t2;j++)
  46. g[j]=min(g[j],g[j-v[i]]+);
  47. }
  48. ans=inf;
  49. for(int i=t;i<=t1;i++)ans=min(ans,f[i]+g[i-t]);
  50. if(ans==inf)printf("-1");
  51. else printf("%d\n",ans);
  52. return ;
  53. }

  bzoj1742: [Usaco2005 nov]Grazing on the Run 边跑边吃草

    好神的DP!居然计算未来的代价!虽然这样中间的状态就都全部是为最后的答案服务,本身是错误的了...

    因为不可能路过草不吃,于是吃的一定是一段连续的区间。

    f[i][j][0]表示吃了 i ~ j ,在 i 的代价,f[i][j][0]就是在 j 的代价。

    f[i][j][0] = min ( f[i+1][j][0] + dis( i , i + 1) * ( n - ( j - i )) , f[i+1][j][1] + dis( i , j ) * ( n - ( j - i ) ));

    之所以* ( n - ( j - i ))是因为走这段路的过程中其他草也会增加腐败度,计算了未来的代价,妙啊

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. int n,m,x,y,z,tot,ans,l,rc;
  13. int f[maxn][],a[maxn];
  14. void read(int &k)
  15. {
  16. int f=;k=;char c=getchar();
  17. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  18. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  19. k*=f;
  20. }
  21. int main()
  22. {
  23. read(n);read(l);
  24. for(int i=;i<=n;i++)read(a[i]);
  25. sort(a+,a++n);
  26. for(int i=;a[i]<=l&&i<=n;i++)f[i][]=f[i][]=(l-a[i])*n,rc=i;
  27. for(int i=rc+;i<=n;i++)f[i][]=f[i][]=(a[i]-l)*n;
  28. for(int i=;i<n;i++)
  29. {
  30. for(int j=;j<=n;j++)
  31. {
  32. f[j][]=min(f[j][]+(a[j+i]-a[j+i-])*(n-i),f[j][]+(a[j+i]-a[j])*(n-i));
  33. f[j][]=min(f[j+][]+(a[j+]-a[j])*(n-i),f[j+][]+(a[j+i]-a[j])*(n-i));
  34. }
  35. }
  36. printf("%d\n",min(f[][],f[][]));
  37. return ;
  38. }

  bzoj1594: [Usaco2008 Jan]猜数游戏

    卡常卡的已经不知道这题怎么写了233,至少上了第一页QAQ  CZL#1 %%%

    二分答案,区间权值降序排序后,用并查集check,具体方法是将某个区间[l,r]的所有数父亲变为l-1,如果r的父亲 < l说明这个区间被完全覆盖了。

    矛盾的情况:①相同权值的区间没有交集②权值大的区间覆盖了权值小的区间的交集

    判断相同权值有没有交集的话只要记录最大的左端点lmax和最小的右端点rmin,如果rmin<lmax就是没交集了。

    于是这个权值一定存在于[lmax,rmin]这个交集,看一下有没有被覆盖就行了。

    因为权值相同的区间一定都有交集所以可以看成一个大区间把lmin到rmax全部指向lmin-1。

    离散化的话如果两个区间的端点没有紧挨着(r1+1<l2),那么要给中间的区间空个格,也就是r1离散化后的值实际比l2离散化后的值少2。

    像这种求被覆盖区间的都可以用并查集

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. struct poi{int pos,sum;}b[maxn];
  13. int n,m,mid,lmax,lmin,rmax,rmin,now,last,rc,noww,l1,r1;
  14. int l[maxn],r[maxn],x[maxn],a[maxn*],pos[maxn],fa[maxn];
  15. void read(int &k)
  16. {
  17. int f=;k=;char c=getchar();
  18. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  19. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  20. k*=f;
  21. }
  22. bool cmp(poi a,poi b){return a.sum>b.sum;}
  23. int gf(int x){return fa[x]==x?x:fa[x]=gf(fa[x]);}
  24. bool check()
  25. {
  26. for(int i=;i<=now;i++)fa[i]=i;
  27. noww=;
  28. while(b[noww].pos>mid)noww++;
  29. lmax=lmin=pos[l[b[noww].pos]],rmax=rmin=pos[r[b[noww].pos]];
  30. rc=;last=noww;
  31. for(int i=noww+;i<=m;i++)
  32. {
  33. if(b[i].pos>mid)continue;
  34. rc++;
  35. if(b[i].sum!=b[last].sum)
  36. {
  37. if(gf(rmin)<lmax)return ;
  38. for(int j=fa[rmax];j>=lmin;j=fa[j])fa[gf(j)]=gf(j-);
  39. lmax=lmin=pos[l[b[i].pos]],rmax=rmin=pos[r[b[i].pos]];
  40. }
  41. else
  42. {
  43. lmax=max(lmax,pos[l[b[i].pos]]);lmin=min(lmin,pos[l[b[i].pos]]);
  44. rmax=max(rmax,pos[r[b[i].pos]]);rmin=min(rmin,pos[r[b[i].pos]]);
  45. if(rmin<lmax)return ;
  46. }
  47. if(rc==mid)break;
  48. last=i;
  49. }
  50. if(gf(rmin)<lmax)return ;
  51. return ;
  52. }
  53. int main()
  54. {
  55. read(n);read(m);
  56. for(int i=;i<=m;i++)read(l[i]),read(r[i]),read(x[i]);
  57. for(int i=;i<=m;i++)a[i<<]=l[i],a[(i<<)-]=r[i];
  58. sort(a+,a++(m<<));
  59. now=;
  60. for(int i=;i<=(m<<);i++,now++)
  61. {
  62. pos[a[i]]=now;
  63. if(a[i]+<a[i+])now++;
  64. }
  65. for(int i=;i<=m;i++)b[i].sum=x[i],b[i].pos=i;
  66. sort(b+,b++m,cmp);
  67. l1=,r1=m;
  68. while(l1<r1)
  69. {
  70. mid=(l1+r1+)>>;
  71. if(check())l1=mid;
  72. else r1=mid-;
  73. }
  74. printf("%d",l1==m?:(l1+));
  75. return ;
  76. }

  bzoj1712: [Usaco2007 China]Summing Sums 加密

    可以发现sum每次都*(n-1)(QAQ我怎么没发现),然后就可以矩阵快速幂了。

    先把矩阵跑出来, 然后乘n次得到n个答案就行了。。。不需要每次都跑个矩阵出来(我傻逼吧

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #define ll long long
  9. using namespace std;
  10. const int maxn=,inf=1e9,mod=;
  11. struct poi{ll mtx[][];}map,g,c;
  12. ll n,m,x,y,z,T,sum;
  13. ll a[maxn];
  14. void read(ll &k)
  15. {
  16. int f=;k=;char c=getchar();
  17. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  18. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  19. k*=f;
  20. }
  21. void merge(poi &a,poi &b)
  22. {
  23. c.mtx[][]=c.mtx[][]=c.mtx[][]=c.mtx[][]=;
  24. for(int i=;i<=;i++)
  25. for(int j=;j<=;j++)
  26. for(int k=;k<=;k++)
  27. c.mtx[i][j]=(c.mtx[i][j]+a.mtx[i][k]*b.mtx[k][j])%mod;
  28. a.mtx[][]=c.mtx[][];a.mtx[][]=c.mtx[][];
  29. a.mtx[][]=c.mtx[][];a.mtx[][]=c.mtx[][];
  30. }
  31. void qsm(int n)
  32. {
  33. while(n)
  34. {
  35. if(n&)merge(map,g);
  36. merge(g,g);
  37. n>>=;
  38. }
  39. }
  40. int main()
  41. {
  42. read(n);read(T);
  43. for(int i=;i<=n;i++)read(a[i]);
  44. for(int i=;i<=n;i++)sum=(sum+a[i])%mod;
  45. map.mtx[][]=map.mtx[][]=;map.mtx[][]=map.mtx[][]=;
  46. g.mtx[][]=-;g.mtx[][]=;g.mtx[][]=;g.mtx[][]=n-;
  47. qsm(T);
  48. for(int i=;i<=n;i++)printf("%lld\n",(map.mtx[][]*a[i]+map.mtx[][]*sum)%mod);
  49. return ;
  50. }

  bzoj1916: [Usaco2010 Open]冲浪

    DP。f[i][j][1]表示第i个点,失控了j次,这一次会失控。f[i][j][0]表示第i个点,失控了j次,这一次不会失控。

    会失控就找到最小的,不会失控就找最大的,两者取最小值就是至少能得到的。

    f[i][j][1]=min(f[i][j][1],min(f[e[i].too][j-1][1],f[e[i].too][j-1][0])+e[i].sum);

    f[i][j][0]=max(f[i][j][0],min(f[e[i].too][j][1],f[e[i].too][j][0])+e[i].sum);

    看了题解才知道最后一维省略其实更好写,我好傻QAQ

    f[i][j]=min(min(f[e[i].too][j-1]+e[i].sum),max(f[e[i].too][j]+e[i].sum))。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. struct poi{ll too,sum,pre;}e[maxn*];
  13. ll n,m,k,x,y,z,tot,ans;
  14. ll f[maxn][][],last[maxn];
  15. bool v[maxn];
  16. void read(ll &k)
  17. {
  18. int f=;k=;char c=getchar();
  19. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  20. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  21. k*=f;
  22. }
  23. void add(int x,int y,int z){e[++tot].too=y;e[tot].sum=z;e[tot].pre=last[x];last[x]=tot;}
  24. int min(int x,int y)
  25. {
  26. if(x<)return y;
  27. if(y<)return x;
  28. return x>y?y:x;
  29. }
  30. void dfs(int x)
  31. {
  32. if(x==n)return;
  33. for(int i=last[x],too=e[i].too;i;i=e[i].pre,too=e[i].too)
  34. if(!v[too])v[too]=,dfs(too);
  35. for(int j=;j<=k;j++)
  36. {
  37. f[x][j][]=1ll*inf*;f[x][j][]=-1ll*inf*;
  38. for(int i=last[x],too=e[i].too;i;i=e[i].pre,too=e[i].too)
  39. {
  40. if(j)f[x][j][]=min(f[x][j][],min(f[too][j-][],f[too][j-][])+e[i].sum);
  41. f[x][j][]=max(f[x][j][],min(f[too][j][],f[too][j][])+e[i].sum);
  42. }
  43. }
  44. }
  45. int main()
  46. {
  47. read(n);read(m);read(k);
  48. for(int i=;i<=m;i++)read(x),read(y),read(z),add(x,y,z);
  49. dfs();
  50. ans=1ll*inf*;
  51. for(int i=;i<=k;i++)
  52. {
  53. ans=min(ans,f[][i][]);
  54. ans=min(ans,f[][i][]);
  55. }
  56. printf("%lld\n",ans);
  57. return ;
  58. }

  bzoj2274: [Usaco2011 Feb]Generic Cow Protests

    MDZZ为什么模数是1e9+9啊???不按常理出牌

    卡了半天常数没快多少还丑了一堆...那还是不卡常好了

    离散化一下前缀和就可以用BIT优化DP了

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9,mod=1e9+;
  12. ll n,x,N;
  13. ll tree[maxn],a[maxn],b[maxn];
  14. void read(ll &k)
  15. {
  16. int f=;k=;char c=getchar();
  17. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  18. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  19. k*=f;
  20. }
  21. int lowbit(ll x){return x&-x;}
  22. void add(ll x,ll y){for(;x<=N;x+=lowbit(x))tree[x]=tree[x]+y,(tree[x]>=mod)&&(tree[x]-=mod);}
  23. int find(ll x){ll sum=;for(;x;x-=lowbit(x))sum=sum+tree[x],sum>=mod&&(sum-=mod);return sum;}
  24. int main()
  25. {
  26. read(n);
  27. for(int i=;i<=n;i++)read(a[i]),a[i]+=a[i-],b[++N]=a[i];N++;
  28. sort(b+,b++N);N=unique(b+,b++N)-b-;
  29. for(int i=;i<=n;i++)a[i]=lower_bound(b+,b++N,a[i])-b;
  30. x=lower_bound(b+,b++N,)-b;
  31. add(x,);
  32. for(int i=;i<=n;i++)
  33. {
  34. x=find(a[i]);
  35. x>=mod&&(x-=mod);
  36. add(a[i],x);
  37. }
  38. printf("%lld\n",x);
  39. return ;
  40. }

  bzoj2097: [Usaco2010 Dec]Exercise 奶牛健美操

    二分+树形DP+贪心

    把所有子树的最长长度排序,某棵子树如果最长长度超过mid就切,否则如果最长+次长超过mid就切最长。

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. #include<algorithm>
  6. using namespace std;
  7. const int maxn=,inf=1e9;
  8. struct poi{int too,pre;}e[maxn];
  9. int n,s,x,y,l,r,mid,tot,ans,cnt;
  10. int a[maxn],b[maxn],fir[maxn],last[maxn];
  11. void read(int &k)
  12. {
  13. int f=;k=;char c=getchar();
  14. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  15. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  16. k*=f;
  17. }
  18. void add(int x,int y){e[++tot].too=y;e[tot].pre=last[x];last[x]=tot;}
  19. bool dfs(int x,int fa)
  20. {
  21. int cnt=;
  22. for(int i=last[x];i;i=e[i].pre)
  23. if(e[i].too!=fa)if(!dfs(e[i].too,x))return ;
  24. for(int i=last[x];i;i=e[i].pre)
  25. if(e[i].too!=fa)b[++cnt]=fir[e[i].too]+;
  26. sort(b+,b++cnt);
  27. for(;cnt;cnt--)
  28. {
  29. if(b[cnt]>mid)ans++;
  30. else if(b[cnt]+b[cnt-]>mid)ans++;
  31. else break;
  32. if(ans>s)return ;
  33. }
  34. fir[x]=b[cnt];
  35. return ;
  36. }
  37. int main()
  38. {
  39. read(n);read(s);if(n==n-){puts("");return ;}if(n==n-){puts("");return ;}
  40. for(int i=;i<n;i++)read(x),read(y),add(x,y),add(y,x);
  41. l=;r=n-;
  42. while(l<r)
  43. {
  44. ans=;
  45. mid=(l+r)>>;
  46. if(dfs(,))r=mid;
  47. else l=mid+;
  48. }
  49. printf("%d\n",l);
  50. }

  bzoj1735: [Usaco2005 jan]Muddy Fields 泥泞的牧场

    同一行连通,同一列连通的行和列标同样的号,然后二分图最大匹配,同bzoj1741

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #define ll long long
  9. using namespace std;
  10. const int maxn=,inf=1e9,dx[]={,,,-},dy[]={,,-,};
  11. struct poi{int too,pre;}e[maxn];
  12. int n,m,x,y,z,tot,rowcnt,clncnt,t,ans;
  13. int last[maxn],lin[maxn],row[maxn][maxn],cln[maxn][maxn],vv[maxn];
  14. bool map[maxn][maxn];
  15. char s[maxn];
  16. void read(int &k)
  17. {
  18. int f=;k=;char c=getchar();
  19. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  20. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  21. k*=f;
  22. }
  23. void add(int x,int y){e[++tot].too=y;e[tot].pre=last[x];last[x]=tot;}
  24. bool xyl(int x)
  25. {
  26. for(int i=last[x];i;i=e[i].pre)
  27. if(vv[e[i].too]!=t)
  28. {
  29. vv[e[i].too]=t;
  30. if((!lin[e[i].too])||xyl(lin[e[i].too]))
  31. {
  32. lin[e[i].too]=x;
  33. return ;
  34. }
  35. }
  36. return ;
  37. }
  38. int main()
  39. {
  40. read(n);read(m);
  41. for(int i=;i<=n;i++)
  42. {
  43. scanf("%s",s+);
  44. for(int j=;j<=m;j++)
  45. map[i][j]=(s[j]=='*');
  46. }
  47. for(int i=;i<=n;i++)
  48. {
  49. rowcnt++;
  50. for(int j=;j<=m;j++)
  51. if(!map[i][j])rowcnt++;
  52. else row[i][j]=rowcnt;
  53. }
  54. for(int i=;i<=m;i++)
  55. {
  56. clncnt++;
  57. for(int j=;j<=n;j++)
  58. if(!map[j][i])clncnt++;
  59. else cln[j][i]=clncnt;
  60. }
  61. for(int i=;i<=n;i++)
  62. for(int j=;j<=m;j++)
  63. if(map[i][j])
  64. add(row[i][j],cln[i][j]);
  65. for(int i=;i<=rowcnt;i++)t++,ans+=xyl(i);
  66. printf("%d\n",ans);
  67. return ;
  68. }

  bzoj1738: [Usaco2005 mar]Ombrophobic Bovines 发抖的牛

    没输出-1 WA了一万次,很伤心

    先跑floyed,二分答案,小于这个答案的边加入,跑最大流check

    这种所有牛同时出发找最短时间的一般都是二分,一开始以为是总时间想写费用流才发现不对QAQ

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=;
  12. const ll inf=;
  13. struct poi{ll too,pre,cf;}e[];
  14. ll n,m,tot,ans,x,y,z,front,rear,sum;
  15. ll l,r,mid,cnt,mx;
  16. ll h[maxn],v[maxn],last[maxn],dis[maxn],cur[maxn],a[maxn],b[maxn];
  17. ll f[][];
  18. void read(ll &k)
  19. {
  20. int f=;k=;char c=getchar();
  21. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  22. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  23. k*=f;
  24. }
  25. void add(int x,int y,ll z)
  26. {
  27. e[++tot].too=y;e[tot].cf=z;e[tot].pre=last[x];last[x]=tot;
  28. e[++tot].too=x;e[tot].cf=;e[tot].pre=last[y];last[y]=tot;
  29. }
  30. bool bfs()
  31. {
  32. for(int i=;i<=sum;i++)v[i]=,dis[i]=-;
  33. dis[]=;v[]=;h[]=;front=;rear=;
  34. while(front!=rear)
  35. {
  36. int now=h[++front];if(front==maxn)front=-;
  37. for(int i=last[now];i;i=e[i].pre)
  38. {
  39. int too=e[i].too;
  40. if((!v[too])&&e[i].cf)
  41. {
  42. dis[too]=dis[now]+;if(too==sum)return ;
  43. v[too]=;h[++rear]=too;if(rear==maxn)rear=-;
  44. }
  45. }
  46. }
  47. return ;
  48. }
  49. int dfs(int x,ll f)
  50. {
  51. int flow=,tmp;
  52. if(x==sum)return f;
  53. for(ll &i=cur[x];i;i=e[i].pre)
  54. {
  55. int too=e[i].too;
  56. if(dis[too]==dis[x]+&&e[i].cf)
  57. {
  58. tmp=dfs(too,min(f-flow,e[i].cf));
  59. e[i].cf-=tmp;e[i^].cf+=tmp;flow+=tmp;
  60. if(f==flow)return f;
  61. }
  62. }
  63. return flow;
  64. }
  65. void dinic()
  66. {
  67. while(bfs())
  68. {
  69. for(int i=;i<=sum;i++)cur[i]=last[i];
  70. ans+=dfs(,inf);
  71. }
  72. }
  73. bool check()
  74. {
  75. memset(last,,sizeof(last));memset(dis,,sizeof(dis));tot=;
  76. for(int i=;i<=n;i++)add(,i,a[i]),add(i,i+n,inf),add(i+n,sum,b[i]);
  77. for(int i=;i<=n;i++)
  78. for(int j=;j<=n;j++)
  79. if(f[i][j]<=mid)add(i,j+n,inf);
  80. ans=;
  81. dinic();
  82. return ans==cnt;
  83. }
  84. int main()
  85. {
  86. tot=;
  87. read(n);read(m);sum=*n+;
  88. for(int i=;i<=n;i++)read(a[i]),read(b[i]),cnt+=a[i];
  89. for(int i=;i<=n;i++)for(int j=;j<=n;j++)f[i][j]=inf;
  90. for(int i=;i<=n;i++)f[i][i]=;
  91. for(int i=;i<=m;i++)read(x),read(y),read(z),f[x][y]=min((ll)z,f[x][y]),f[y][x]=f[x][y],mx+=f[x][y];
  92. for(int k=;k<=n;k++)
  93. for(int i=;i<=n;i++)
  94. for(int j=;j<=n;j++)
  95. f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
  96. l=;r=mx+;
  97. while(l<r)
  98. {
  99. mid=(l+r)>>;
  100. if(check())r=mid;
  101. else l=mid+;
  102. }
  103. if(r==(mx+)&&(!check()))printf("-1");
  104. else printf("%lld\n",l);
  105. return ;
  106. }

  bzoj1740: [Usaco2005 mar]Yogurt factory 奶酪工厂

    记录一下之前的费用最小值和现在比较就行了...之前被HR一眼秒过

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. #define ll long long
  6. using namespace std;
  7. const int maxn=,inf=1e9;
  8. ll n,s,c,y,mn,ans;
  9. void read(ll &k)
  10. {
  11. int f=;k=;char c=getchar();
  12. while(c<''||c>'')f=='-'&&(c=-),c=getchar();
  13. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  14. k*=f;
  15. }
  16. int main()
  17. {
  18. read(n);read(s);
  19. mn=inf;
  20. for(int i=;i<=n;i++)
  21. {
  22. read(c);read(y);
  23. mn=min(mn+s,c);
  24. ans+=mn*y;
  25. }
  26. printf("%lld\n",ans);
  27. }

  bzoj2099: [Usaco2010 Dec]Letter 恐吓信

    不会SAM(躺

    显然每次砍LCP就行。

    先跑出A串的SA,这样就排好了每个后缀的字典序,于是在A串中二分找到B串的字典序位置 l,LCP一定是B串与sa[l]或sa[l+1]开始的后缀的LCP,然后logn求LCP就行了。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #define ull unsigned long long
  6. using namespace std;
  7. const int maxn=;
  8. int n,m,p,ans,mm;
  9. int sum[maxn],rk[maxn],sa[maxn],trk[maxn],tsa[maxn];
  10. ull hs1[maxn],hs2[maxn],mul[maxn];
  11. char s[maxn],s2[maxn];
  12. void read(int &k)
  13. {
  14. int f=;k=;char c=getchar();
  15. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  16. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  17. k*=f;
  18. }
  19. void suffix()
  20. {
  21. for(int i=;i<=n;i++)sum[s[i]]++;
  22. for(int i=;i<=;i++)sum[i]+=sum[i-];
  23. for(int i=n;i;i--)sa[sum[s[i]]]=i,sum[s[i]]--;
  24. rk[sa[]]=;p=;
  25. for(int i=;i<=n;i++)rk[sa[i]]=(s[sa[i]]!=s[sa[i-]])?++p:p;
  26. m=p;int j=;
  27. while(m<n)
  28. {
  29. memcpy(trk,rk,sizeof(rk));memset(sum,,sizeof(sum));p=;
  30. for(int i=n-j+;i<=n;i++)tsa[++p]=i;
  31. for(int i=;i<=n;i++)if(sa[i]>j)tsa[++p]=sa[i]-j;
  32. for(int i=;i<=n;i++)rk[i]=trk[tsa[i]],sum[rk[i]]++;
  33. for(int i=;i<=m;i++)sum[i]+=sum[i-];
  34. for(int i=n;i;i--)sa[sum[rk[i]]]=tsa[i],sum[rk[i]]--;
  35. rk[sa[]]=;p=;
  36. for(int i=;i<=n;i++)rk[sa[i]]=(trk[sa[i]]!=trk[sa[i-]]||trk[sa[i]+j]!=trk[sa[i-]+j])?++p:p;
  37. m=p;j*=;
  38. }
  39. }
  40. int lcp(int a,int b)
  41. {
  42. int l=,r=min(n-a+,mm-b+);
  43. while(l<r)
  44. {
  45. int mid=(l+r+)>>;
  46. ull hsa=hs1[a]-hs1[a+mid]*mul[mid],hsb=hs2[b]-hs2[b+mid]*mul[mid];
  47. if(hsa!=hsb)r=mid-;
  48. else l=mid;
  49. }
  50. return l;
  51. }
  52. int main()
  53. {
  54. read(n);read(mm);
  55. for(int i=;i<=n;i++)
  56. for(s[i]=getchar();s[i]<'A'||s[i]>'Z';s[i]=getchar());
  57. suffix();
  58. mul[]=;
  59. for(int i=;i<=n;i++)mul[i]=mul[i-]*;
  60. for(int i=n;i;i--)hs1[i]=hs1[i+]*+1ull*(s[i]-'A');
  61. for(int i=;i<=mm;i++)
  62. for(s2[i]=getchar();s2[i]<'A'||s2[i]>'Z';s2[i]=getchar());
  63. for(int i=mm;i;i--)hs2[i]=hs2[i+]*+1ull*(s2[i]-'A');
  64. for(int i=;i<=mm;)
  65. {
  66. int l=,r=n;
  67. while(l<r)
  68. {
  69. int mid=(l+r+)>>;
  70. int len=lcp(sa[mid],i);
  71. if(s[sa[mid]+len]<s2[i+len])l=mid;
  72. else r=mid-;
  73. }
  74. i+=max(lcp(sa[l],i),lcp(sa[l+],i));
  75. ans++;
  76. }
  77. printf("%d\n",ans);
  78. }

  bzoj3408: [Usaco2009 Oct]Heat Wave 热浪

    太年轻了一直不敢下手,就是个最短路而已= =

    同样年轻的LLQ大佬

    不贴代码了这博客要炸了

  bzoj1744: [Usaco2005 oct]Skiing 奶牛滑雪

    好强的题!正着来不行,倒着跑就可以了。从n,m到1,1,走过哪条边就给原来后面的距离除以这条边对速度的影响。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,dx[]={,,,-},dy[]={,,-,};
  12. int n,m,x,y,z,tot,v0,nx,ny;
  13. int h[maxn*][],front,rear,ht[maxn][maxn];
  14. ll mi[maxn];
  15. double dist[maxn][maxn],fumi[maxn];
  16. bool v[maxn][maxn];
  17. void read(int &k)
  18. {
  19. int f=;k=;char c=getchar();
  20. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  21. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  22. k*=f;
  23. }
  24. double get(int x,int y)
  25. {
  26. if(x>y)return mi[x-y];
  27. return fumi[y-x];
  28. }
  29. void spfa(int x,int y)
  30. {
  31. double inf=<<;inf*=inf;
  32. for(int i=;i<=n;i++)for(int j=;j<=m;j++)dist[i][j]=inf;
  33. h[][]=x;h[][]=y;front=;rear=;v[x][y]=;dist[x][y]=0.0;
  34. while(front!=rear)
  35. {
  36. nx=h[++front][];ny=h[front][];if(front==maxn*)front=-;
  37. for(int i=;i<;i++)
  38. {
  39. int xx=nx+dx[i],yy=ny+dy[i];
  40. if(xx<||xx>n||yy<||yy>m)continue;
  41. if(dist[xx][yy]>dist[nx][ny]/get(ht[xx][yy],ht[nx][ny])+1.0)
  42. {
  43. dist[xx][yy]=dist[nx][ny]/get(ht[xx][yy],ht[nx][ny])+1.0;
  44. if(!v[xx][yy])
  45. {
  46. v[xx][yy]=;h[++rear][]=xx;h[rear][]=yy;
  47. if(rear==maxn*)rear=-;
  48. }
  49. }
  50. }
  51. v[nx][ny]=;
  52. }
  53. }
  54. int main()
  55. {
  56. read(v0);read(n);read(m);
  57. mi[]=;fumi[]=1.0;
  58. for(int i=;i<=;i++)mi[i]=mi[i-]*;
  59. for(int i=;i<=;i++)fumi[i]=fumi[i-]/;
  60. for(int i=;i<=n;i++)
  61. for(int j=;j<=m;j++)
  62. read(ht[i][j]);
  63. spfa(n,m);
  64. printf("%.2lf\n",dist[][]/v0);
  65. return ;
  66. }

  bzoj1752: [Usaco2005 qua]Til the Cows Come Home

    同上上题...nm看反WA了4次T_T

  bzoj1733: [Usaco2005 feb]Secret Milking Machine 神秘的挤奶机

    二分,长度<=mid就加入,网络流check

    看样子很多人的网络流都没加当前弧优化?加了之后就上第一页了...

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. struct poi{int too,pre,cf;}e[maxn];
  13. int n,m,tot,ans,front,rear,mid,t,l,r;
  14. int h[maxn],v[maxn],last[],dis[maxn],cur[maxn],x[maxn],y[maxn],z[maxn];
  15. void read(int &k)
  16. {
  17. int f=;k=;char c=getchar();
  18. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  19. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  20. k*=f;
  21. }
  22. void add(int x,int y,int z)
  23. {
  24. e[++tot].too=y;e[tot].cf=z;e[tot].pre=last[x];last[x]=tot;
  25. e[++tot].too=x;e[tot].cf=;e[tot].pre=last[y];last[y]=tot;
  26. }
  27. bool bfs()
  28. {
  29. for(int i=;i<=n;i++)v[i]=,dis[i]=-;
  30. dis[]=;v[]=;h[]=;front=;rear=;
  31. while(front!=rear)
  32. {
  33. int now=h[++front];if(front==maxn)front=-;
  34. for(int i=last[now];i;i=e[i].pre)
  35. {
  36. int too=e[i].too;
  37. if((!v[too])&&e[i].cf)
  38. {
  39. dis[too]=dis[now]+;if(too==n)return ;
  40. v[too]=;h[++rear]=too;if(rear==maxn)rear=-;
  41. }
  42. }
  43. }
  44. return ;
  45. }
  46. int dfs(int x,int f)
  47. {
  48. int flow=,tmp;
  49. if(x==n)return f;
  50. for(int &i=cur[x];i;i=e[i].pre)
  51. {
  52. int too=e[i].too;
  53. if(dis[too]==dis[x]+&&e[i].cf)
  54. {
  55. tmp=dfs(too,min(f-flow,e[i].cf));
  56. e[i].cf-=tmp;e[i^].cf+=tmp;flow+=tmp;
  57. if(f==flow)return f;
  58. }
  59. }
  60. return flow;
  61. }
  62. void dinic()
  63. {
  64. while(bfs())
  65. {
  66. for(int i=;i<=n;i++)cur[i]=last[i];
  67. ans+=dfs(,inf);
  68. }
  69. }
  70. bool check()
  71. {
  72. tot=;memset(last,,sizeof(last));
  73. for(int i=;i<=m;i++)
  74. if(z[i]<=mid)
  75. {
  76. add(x[i],y[i],);
  77. add(y[i],x[i],);
  78. }
  79. ans=;
  80. dinic();
  81. return ans>=t;
  82. }
  83. int main()
  84. {
  85. read(n);read(m);read(t);l=inf;r=-inf;
  86. for(int i=;i<=m;i++)read(x[i]),read(y[i]),read(z[i]),l=min(l,z[i]),r=max(r,z[i]);
  87. while(l<r)
  88. {
  89. mid=(l+r)>>;
  90. if(check())r=mid;
  91. else l=mid+;
  92. }
  93. printf("%d\n",l);
  94. return ;
  95. }

  bzoj2196: [Usaco2011 Mar]Brownie Slicing

    二分,再套个二分检验。。。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. ll n,m,x,y,z,tot,cnt,A,B,l,r,mid,mid2,now;
  13. ll a[maxn][maxn],sum[maxn][maxn];
  14. void read(ll &k)
  15. {
  16. int f=;k=;char c=getchar();
  17. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  18. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  19. k*=f;
  20. }
  21. bool checkcheck()
  22. {
  23. int ans=,last=;
  24. for(int i=;i<=m;i++)
  25. if(sum[mid2][i]-sum[now-][i]-sum[mid2][last-]+sum[now-][last-]>=mid)
  26. {
  27. last=i+;
  28. ans++;
  29. if(ans==B)return ;
  30. }
  31. return ;
  32. }
  33. bool check()
  34. {
  35. now=;
  36. for(int i=;i<=A;i++)
  37. {
  38. int l=now,r=n;
  39. while(l<r)
  40. {
  41. mid2=(l+r)>>;
  42. if(checkcheck())r=mid2;
  43. else l=mid2+;
  44. }
  45. if(i==A)return mid2=(l+r)>>,checkcheck();
  46. now=l+;
  47. if(now>n)return ;
  48. }
  49. return ;
  50. }
  51. int main()
  52. {
  53. read(n);read(m);read(A);read(B);
  54. for(int i=;i<=n;i++)
  55. for(int j=;j<=m;j++)
  56. read(a[i][j]),cnt+=a[i][j],sum[i][j]=sum[i-][j]+sum[i][j-]-sum[i-][j-]+a[i][j];
  57. l=;r=cnt/A/B;
  58. while(l<r)
  59. {
  60. mid=(l+r+)>>;
  61. if(check())l=mid;
  62. else r=mid-;
  63. }
  64. printf("%lld\n",l);
  65. return ;
  66. }

  bzoj1739: [Usaco2005 mar]Space Elevator 太空电梯

    做n次多重背包

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. struct poi{int h,limit,c;}a[maxn];
  13. int n,m,x,y,z,tot,ans;
  14. int f[maxn];
  15. void read(int &k)
  16. {
  17. int f=;k=;char c=getchar();
  18. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  19. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  20. k*=f;
  21. }
  22. bool cmp(poi a,poi b){return a.limit<b.limit;}
  23. int main()
  24. {
  25. read(n);
  26. for(int i=;i<=n;i++)read(a[i].h),read(a[i].limit),read(a[i].c);
  27. sort(a+,a++n,cmp);
  28. for(int i=;i<=n;i++)
  29. for(int j=a[i].limit;j>=a[i].h;j--)
  30. for(int k=;k<=a[i].c;k++)
  31. {
  32. if(k*a[i].h>j)break;
  33. f[j]=max(f[j],f[j-k*a[i].h]+k*a[i].h);
  34. }
  35. for(int i=;i<=a[n].limit;i++)ans=max(f[i],ans);
  36. printf("%d\n",ans);
  37. return ;
  38. }

  bzoj2501: [usaco2010 Oct]Soda Machine

    差分

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. #include<algorithm>
  6. using namespace std;
  7. const int maxn=;
  8. struct poi{int sum,pos;}a[maxn];
  9. int n,now,ans,cnt;
  10. void read(int &k)
  11. {
  12. int f=;k=;char c=getchar();
  13. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  14. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  15. k*=f;
  16. }
  17. bool cmp(poi a,poi b){return a.sum<b.sum;}
  18. int main()
  19. {
  20. read(n);
  21. for(int i=;i<=n;i++)read(a[++cnt].sum),a[cnt].pos=,read(a[++cnt].sum),a[cnt].sum++,a[cnt].pos=-;
  22. sort(a+,a++cnt,cmp);
  23. for(int i=;i<=cnt;i++)
  24. {
  25. now+=a[i].pos;
  26. if(a[i].sum!=a[i+].sum)
  27. ans=max(ans,now);
  28. }
  29. printf("%d\n",ans);
  30. }

  bzoj2590: [Usaco2012 Feb]Cow Coupons

    网上题解大部分是错的。。。包括黄学长的也被我hack了。还有一个博客大小写反了= =,但是代码是对的

    首先肯定选k个优惠券最小的,如果不够选直接输出。如果还有多余的钱的话,比较一下(已买的里面原价与优惠价的最小差价+没买的里面的最小优惠价)和(没买的里面的最小原价),选一个小的。第一个实际上相当于把优惠卷花钱赎回来。。。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. struct poi{ll sum,i;}qq1,qq2,qq3;
  13. struct zs{ll p,c;}a[maxn];
  14. priority_queue<poi>q1,q2,q3;
  15. bool operator<(poi a,poi b){return a.sum>b.sum;}
  16. ll n,m,k,x,y,z,tot,cost,ans;
  17. bool v[maxn];
  18. void read(ll &k)
  19. {
  20. int f=;k=;char c=getchar();
  21. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  22. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  23. k*=f;
  24. }
  25. bool cmp(zs a,zs b){return a.c<b.c;}
  26. int main()
  27. {
  28. read(n);read(k);read(m);
  29. for(int i=;i<=n;i++)read(a[i].p),read(a[i].c);
  30. sort(a+,a++n,cmp);
  31. for(int i=;i<=k;i++)
  32. {
  33. cost+=a[i].c;
  34. if(cost>m){printf("%d\n",i-);return ;}
  35. }
  36. for(int i=;i<=k;i++)q1.push((poi){a[i].p-a[i].c,i});
  37. for(int i=k+;i<=n;i++)q2.push((poi){a[i].c,i}),q3.push((poi){a[i].p,i});
  38. ans=k;v[]=;
  39. while(cost<m)
  40. {
  41. if(!q1.empty())qq1=q1.top(),q1.pop();else qq1.sum=inf;
  42. if(!q2.empty())for(qq2=q2.top(),q2.pop();v[qq2.i]&&(!q2.empty());q2.pop())qq2=q2.top();else qq2.sum=inf,qq2.i=;
  43. if(v[qq2.i])qq2.sum=inf;
  44. if(!q3.empty())for(qq3=q3.top(),q3.pop();v[qq3.i]&&(!q3.empty());q3.pop())qq3=q3.top();else qq3.sum=inf,qq3.i=;
  45. if(v[qq3.i])qq3.sum=inf;
  46. if(qq1.sum+qq2.sum>qq3.sum)
  47. {
  48. cost+=qq3.sum;
  49. if(qq1.sum!=inf)q1.push((poi){qq1.sum,qq1.i});
  50. if(qq2.sum!=inf)q2.push((poi){qq2.sum,qq2.i});
  51. }
  52. else
  53. {
  54. cost+=qq1.sum+qq2.sum;
  55. if(qq3.sum!=inf)q3.push((poi){qq3.sum,qq3.i});
  56. }
  57. if(cost<=m)ans++;
  58. if(ans==n)break;
  59. }
  60. printf("%lld\n",ans);
  61. return ;
  62. }

  bzoj1986: [USACO2004 Dec] Dividing the Path 划区灌溉

    傻逼题调了半天。。怎么最近老是不能1A啊。。。总是出奇奇怪怪的错误

    f[i]表示0~i被灌溉的最少喷灌器。

    f[i]=min(f[j])+1;(i-2*B<=j<=I-2*A)

    如果i在(l[i],r[i])中,f[i]=inf;

    单调队列优化即可

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. int n,m,x,y,z,tot,l,r,L,A,B,now;
  13. int f[maxn],q[maxn],sum[maxn],v[maxn];
  14. void read(int &k)
  15. {
  16. int f=;k=;char c=getchar();
  17. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  18. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  19. k*=f;
  20. }
  21. int main()
  22. {
  23. read(n);read(L);read(A);read(B);
  24. for(int i=;i<=n;i++)
  25. {
  26. read(x);read(y);
  27. if(x+==y)continue;
  28. sum[x+]++;sum[y]--;
  29. }
  30. l=;r=;
  31. for(int i=;i<=L;i++)
  32. {
  33. now+=sum[i];v[i]=now;
  34. if(i&)continue;
  35. if((!v[i-*A])&&i-*A>=)
  36. {
  37. while(l<=r&&f[q[r]]>f[i-*A])r--;
  38. q[++r]=i-*A;
  39. }
  40. while(l<=r&&(i-q[l]>*B))l++;
  41. f[i]=(l>r)?inf:f[q[l]]+;
  42. }
  43. printf("%d\n",f[L]<inf?f[L]:-);
  44. return ;
  45. }

  bzoj1722: [Usaco2006 Mar] Milk Team Select 产奶比赛

    早上打hihocoder暴力分都没拿满好惨啊QAQ

    这破题还调了好久,我好傻逼

    一眼树形DP。f[i][j][0/1] 有 j 对亲属关系,节点 i 选/不选。

    对每个子树做多重背包就行了。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. struct poi{int too,pre;}e[maxn*];
  13. int n,m,x,y,z,tot,X;
  14. int f[maxn][maxn][],a[maxn],last[maxn],size[maxn],son[maxn];
  15. void read(int &k)
  16. {
  17. int f=;k=;char c=getchar();
  18. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  19. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  20. k*=f;
  21. }
  22. void add(int x,int y){e[++tot].too=y;e[tot].pre=last[x];last[x]=tot;}
  23. void dfs(int x)
  24. {
  25. f[x][][]=;f[x][][]=a[x];
  26. for(int i=last[x];i;i=e[i].pre)dfs(e[i].too),size[x]+=size[e[i].too]+,son[x]++;
  27. for(int i=last[x];i;i=e[i].pre)
  28. for(int j=size[x];j>=;j--)
  29. {
  30. for(int k=;k<=min(j,size[e[i].too]);k++)
  31. {
  32. if(j<=size[x]-son[x])f[x][j][]=max(f[x][j][],f[x][j-k][]+max(f[e[i].too][k][],f[e[i].too][k][]));
  33. f[x][j][]=max(f[x][j][],f[x][j-k][]+max(f[e[i].too][k][],k!=?f[e[i].too][k-][]:-inf));
  34. }
  35. if(j>size[e[i].too])f[x][j][]=max(f[x][j][],f[x][j-size[e[i].too]-][]+f[e[i].too][size[e[i].too]][]);
  36. }
  37. //for(int i=0;i<=size[x];i++)printf("x:%d i:%d fxi0:%d fxi1:%d\n",x,i,f[x][i][0],f[x][i][1]);
  38. }
  39. int main()
  40. {
  41. read(n);read(X);
  42. for(int i=;i<=n;i++)
  43. {
  44. read(a[i]);read(y);
  45. if(y)add(y,i);else add(,i);
  46. }
  47. memset(f,-,sizeof(f));
  48. dfs();
  49. //printf("%d %d\n",f[1][0][0],f[1][0][1]);
  50. for(int i=n-;i>=;i--)if(f[][i][]>=X){printf("%d\n",i);return ;}
  51. printf("-1");
  52. return ;
  53. }

  bzoj2059: [Usaco2010 Nov]Buying Feed 购买饲料

    MDZZ忘记自己开的是long long是8字节。。。初始化老是小了

    简单DP。f[i][j]表示前i个商店,买j吨饲料的最小代价,单调队列优化。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. struct poi{ll x,f,c;}a[maxn];
  13. ll n,m,tot,k,e,l,r;
  14. ll ans,dp[][];
  15. ll q[maxn];
  16. void read(ll &k)
  17. {
  18. int f=;k=;char c=getchar();
  19. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  20. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  21. k*=f;
  22. }
  23. bool cmp(poi a,poi b){return a.x<b.x;}
  24. int main()
  25. {
  26. read(k);read(e);read(n);
  27. for(int i=;i<=n;i++)read(a[i].x),read(a[i].f),read(a[i].c);
  28. sort(a+,a++n,cmp);
  29. memset(dp[],0x7f,(k+)<<);dp[][]=;
  30. for(int i=;i<=n;i++)
  31. {
  32. l=;r=;
  33. for(int j=;j<=k;j++)
  34. {
  35. dp[i][j]=1ll*inf*;
  36. while(l<=r&&j-q[l]>a[i].f)l++;
  37. while(l<=r&&dp[i-][q[r]]-a[i].c*q[r]+q[r]*q[r]*(a[i].x-a[i-].x)>dp[i-][j]-a[i].c*j+j*j*(a[i].x-a[i-].x))r--;
  38. q[++r]=j;
  39. dp[i][j]=(l>r)?(1ll*inf*):dp[i-][q[l]]+a[i].c*(j-q[l])+q[l]*q[l]*(a[i].x-a[i-].x);
  40. }
  41. }
  42. ans=1ll*inf*;
  43. for(int i=;i<=n;i++)
  44. ans=min(ans,dp[i][k]+k*k*(e-a[i].x));
  45. printf("%lld\n",ans);
  46. return ;
  47. }

  bzoj1698: [Usaco2007 Feb]Lilypad Pond 荷叶池塘

    哇日常水题调很久系列。 

    最短路径怎么求很显然,往空地连1,荷叶连0。但是这样会发现在最短路松弛的时候记录的方案数会多算,因为可以走一圈荷叶代价为0再回来最短路径还是不变的,所以我们要想办法把边权0的去掉,就不会出现这种情况了。怎么办呢,提前dfs出两两空地能否不经过其他空地(可经过荷叶)到达就行了,然后连边边权为1,这样就去掉了所有边权为0的边,跑最短路。

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. #define ll long long
  6. using namespace std;
  7. const int maxn=,inf=1e9,dx[]={-,-,,,,,-,-},dy[]={,,,,-,-,-,-};
  8. struct poi{int tox,toy,pre;}e[];
  9. int n,m,cnt,front,rear,tot,sx,sy,tx,ty,tim;
  10. int map[maxn][maxn],b[maxn*maxn][],h[][],dist[maxn][maxn],last[maxn][maxn],vvv[maxn][maxn];
  11. ll ans[maxn][maxn];
  12. bool v[maxn][maxn],vv[maxn][maxn];
  13. void read(int &k)
  14. {
  15. int f=;k=;char c=getchar();
  16. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  17. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  18. k*=f;
  19. }
  20. void add(int x1,int y1,int x2,int y2){e[++tot].tox=x2;e[tot].toy=y2;e[tot].pre=last[x1][y1];last[x1][y1]=tot;}
  21. void spfa(int x,int y)
  22. {
  23. for(int i=;i<=n;i++)for(int j=;j<=m;j++)dist[i][j]=inf;
  24. dist[x][y]=;v[x][y]=;front=;rear=;h[rear][]=x;h[rear][]=y;ans[x][y]=;
  25. while(front!=rear)
  26. {
  27. int nowx=h[++front][],nowy=h[front][];if(front==)front=-;++tim;
  28. //printf("%d %d %d %lld\n",nowx,nowy,dist[nowx][nowy],ans[nowx][nowy]);
  29. for(int i=last[nowx][nowy],tox=e[i].tox,toy=e[i].toy;i;i=e[i].pre,tox=e[i].tox,toy=e[i].toy)
  30. {
  31. if(vvv[tox][toy]==tim)continue;vvv[tox][toy]=tim;
  32. if(dist[tox][toy]==dist[nowx][nowy]+)ans[tox][toy]+=ans[nowx][nowy];
  33. if(dist[tox][toy]>dist[nowx][nowy]+)
  34. {
  35. dist[tox][toy]=dist[nowx][nowy]+;
  36. ans[tox][toy]=ans[nowx][nowy];
  37. if(!v[tox][toy])
  38. {
  39. v[tox][toy]=;h[++rear][]=tox;h[rear][]=toy;
  40. if(rear==)rear=-;
  41. }
  42. }
  43. }
  44. for(int i=;i<;i++)
  45. {
  46. int tox=nowx+dx[i],toy=nowy+dy[i];
  47. if(tox<||tox>n||toy<||toy>m||map[tox][toy]==||vvv[tox][toy]==tim||map[tox][toy]==)continue;
  48. if(dist[tox][toy]==dist[nowx][nowy]+)ans[tox][toy]+=ans[nowx][nowy];
  49. if(dist[tox][toy]>dist[nowx][nowy]+)
  50. {
  51. dist[tox][toy]=dist[nowx][nowy]+;
  52. ans[tox][toy]=ans[nowx][nowy];
  53. if(!v[tox][toy])
  54. {
  55. v[tox][toy]=;h[++rear][]=tox;h[rear][]=toy;
  56. if(rear==)rear=-;
  57. }
  58. }
  59. }
  60. }
  61. }
  62. void dfs(int x,int y)
  63. {
  64. vv[x][y]=;
  65. for(int i=;i<;i++)
  66. {
  67. int xx=x+dx[i],yy=y+dy[i];
  68. if(xx<||xx>n||yy<||yy>m||map[xx][yy]==)continue;
  69. if(map[xx][yy]==&&vv[xx][yy]!=)dfs(xx,yy);
  70. else if(map[xx][yy]!=)b[++cnt][]=xx,b[cnt][]=yy;
  71. }
  72. }
  73. int main()
  74. {
  75. read(n);read(m);
  76. for(int i=;i<=n;i++)
  77. for(int j=;j<=m;j++)
  78. {
  79. read(map[i][j]);
  80. if(map[i][j]==)sx=i,sy=j;
  81. if(map[i][j]==)tx=i,ty=j;
  82. if(map[i][j]==)add(,,i,j);
  83. }
  84. for(int i=last[][];i;i=e[i].pre)
  85. {
  86. cnt=;
  87. if(!vv[e[i].tox][e[i].toy])dfs(e[i].tox,e[i].toy);
  88. for(int j=;j<=cnt;j++)
  89. for(int k=;k<=cnt;k++)
  90. add(b[j][],b[j][],b[k][],b[k][]);
  91. }
  92. spfa(sx,sy);
  93. if(dist[tx][ty]==inf)printf("-1");
  94. else printf("%d\n%lld",dist[tx][ty]-,ans[tx][ty]);
  95. }

  bzoj1777: [Usaco2010 Hol]rocks 石头木头

    阶梯博弈 http://blog.csdn.net/longshuai0821/article/details/7793043

    距离终点偶数长度的不用考虑.某个点的SG值为数量%(l+1),手推可以推出来。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. struct poi{int too,pre;}e[maxn];
  13. int n,m,x,y,z,tot,l,t,ans;
  14. int v[maxn],dis[maxn],last[maxn];
  15. void read(int &k)
  16. {
  17. int f=;k=;char c=getchar();
  18. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  19. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  20. k*=f;
  21. }
  22. void add(int x,int y){e[++tot].too=y;e[tot].pre=last[x];last[x]=tot;}
  23. void dfs(int x)
  24. {
  25. for(int i=last[x];i;i=e[i].pre)
  26. dis[e[i].too]=dis[x]+,dfs(e[i].too);
  27. }
  28. int main()
  29. {
  30. read(n);read(t);read(l);
  31. for(int i=;i<=n;i++)read(x),read(v[i]),add(x,i);
  32. dfs();
  33. for(int i=;i<=n;i++)if(dis[i]&)ans^=v[i]%(l+);
  34. for(int i=;i<=t;i++)
  35. {
  36. read(x);read(y);
  37. if(dis[x]&)ans^=(v[x]%(l+))^(y%(l+));
  38. v[x]=y;
  39. printf("%s\n",ans?"Yes":"No");
  40. }
  41. return ;
  42. }

  bzoj1729: [Usaco2005 dec]Cow Patterns 牛的模式匹配

    嗯昨天调了一天错误代码,最后还是放弃了抄题解吧T_T

    可以预处理出某种数字出现次数的前缀,KMP的时候计算一下这个区间内比自己小的数的个数就是排名。然后再比较两个串这个区间内相同数字的出现次数是否相同,如果这个条件和排名都符合,那么这两位就是可以匹配的。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. int n,m,S,x1,x2,yy1,y2,cnt;
  13. int rk[][maxn][],s[][maxn],f[maxn],ans[maxn];
  14. void read(int &k)
  15. {
  16. int f=;k=;char c=getchar();
  17. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  18. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  19. k*=f;
  20. }
  21. int getrk(int x,int i,int j)
  22. {
  23. x1=x2=yy1=y2=;
  24. for(int k=;k<s[x][i];k++)x1+=rk[x][i][k]-rk[x][i-j][k];
  25. yy1=rk[x][i][s[x][i]]-rk[x][i-j][s[x][i]];
  26. for(int k=;k<s[][j];k++)x2+=rk[][j][k];
  27. y2=rk[][j][s[][j]];
  28. return (x1==x2)&&(yy1==y2);
  29. }
  30. void getfail()
  31. {
  32. f[]=;f[]=;int j;
  33. for(int i=;i<=m;i++)
  34. {
  35. for(j=f[i];j>&&(!getrk(,i,j));j=f[j]);
  36. if(getrk(,i,j))f[i+]=j+;else f[i+]=;
  37. }
  38. }
  39. void kmp()
  40. {
  41. int j=;
  42. for(int i=;i<=n;i++)
  43. {
  44. while(j>&&(!getrk(,i,j)))j=f[j];
  45. if(getrk(,i,j))j++;
  46. if(j==m+)ans[++cnt]=i-m+,j=f[j];
  47. }
  48. }
  49. int main()
  50. {
  51. read(n);read(m);read(S);
  52. for(int i=;i<=n;i++)read(s[][i]);
  53. for(int i=;i<=m;i++)read(s[][i]);
  54. for(int i=;i<=n;i++)
  55. {
  56. for(int j=;j<=S;j++)rk[][i][j]=rk[][i-][j];
  57. rk[][i][s[][i]]++;
  58. }
  59. for(int i=;i<=m;i++)
  60. {
  61. for(int j=;j<=S;j++)rk[][i][j]=rk[][i-][j];
  62. rk[][i][s[][i]]++;
  63. }
  64. getfail();kmp();
  65. printf("%d\n",cnt);
  66. for(int i=;i<=cnt;i++)printf("%d\n",ans[i]);
  67. return ;
  68. }

  bzoj1605: [Usaco2008 Open]Crisis on the Farm 牧场危机

    mdzz被输出方案最小字典序坑了好久TAT

    预处理get[i][j]表示横坐标移动 i ,纵坐标移动 j 最后一步能救的牛。

    f[i][j][k]表示已经走了i步,横坐标移动 j ,纵坐标移动 k最多能救几头牛,从四个方向转移+get[j][k]就行了。

    方案就记录从哪转移来的,最小字典序我写了半天顺序实在调不下去了干脆写了个哈希来判...终于过了QAQ(蠢哭

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ull unsigned long long
  10. using namespace std;
  11. const int maxn=,inf=1e9,dx[]={-,,,},dy[]={,-,,};
  12. int n,m,K,x,y,z,tot,ans,posx,posy;
  13. int f[][][],from[][][][],cowx[maxn],cowy[maxn],grax[maxn],gray[maxn],get[][];
  14. ull hs[][][],hss;
  15. char anss[];
  16. void read(int &k)
  17. {
  18. int f=;k=;char c=getchar();
  19. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  20. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  21. k*=f;
  22. }
  23. int main()
  24. {
  25. read(n);read(m);read(K);
  26. for(int i=;i<=n;i++)read(cowx[i]),read(cowy[i]);
  27. for(int i=;i<=m;i++)
  28. {
  29. read(grax[i]),read(gray[i]);
  30. for(int j=;j<=n;j++)
  31. if(abs(grax[i]-cowx[j])+abs(gray[i]-cowy[j])<=K)
  32. get[grax[i]-cowx[j]+][gray[i]-cowy[j]+]++;
  33. }
  34. memset(f,-,sizeof(f));
  35. f[][][]=;
  36. for(int i=;i<=K;i++)
  37. {
  38. for(int j=-i;j<=i;j++)
  39. {
  40. for(int k=-i;k<=i;k++)
  41. if(abs(j)+abs(k)<=i)
  42. {
  43. for(int l=;l<;l++)
  44. {
  45. int x=j+dx[l],y=k+dy[l];
  46. if(f[i-][x+][y+]+get[j+][k+]>f[i][j+][k+]||(f[i-][x+][y+]+get[j+][k+]==f[i][j+][k+]&&hs[i-][x+][y+]*+l<hs[i][j+][k+]))
  47. {
  48. f[i][j+][k+]=f[i-][x+][y+]+get[j+][k+];
  49. from[i][j+][k+][]=x;from[i][j+][k+][]=y;
  50. hs[i][j+][k+]=hs[i-][x+][y+]*+l;
  51. }
  52. }
  53. if(f[i][j+][k+]>ans||(f[i][j+][k+]==ans&&hs[i][j+][k+]<hss))
  54. {
  55. ans=f[i][j+][k+];
  56. hss=hs[i][j+][k+];
  57. posx=j;posy=k;
  58. }
  59. }
  60. }
  61. }
  62. printf("%d\n",ans);
  63. for(int i=K;i;i--)
  64. {
  65. int nx=from[i][posx+][posy+][],ny=from[i][posx+][posy+][];
  66. if(nx==posx)
  67. {
  68. if(ny>posy)anss[i]='S';
  69. else anss[i]='N';
  70. }
  71. else
  72. {
  73. if(nx>posx)anss[i]='W';
  74. else anss[i]='E';
  75. }
  76. posx=nx;posy=ny;
  77. }
  78. for(int i=;i<=K;i++)printf("%c",anss[i]);
  79. return ;
  80. }

  bzoj3126: [Usaco2013 Open]Photo

    噗哈哈看网上的题解全是DP+线段树或者单调队列优化,一眼差分约束,结果写差分约束真的艹过去了233(虽然跑的奇慢

    对于一个区间[l,r],有条件sum[r]-sum[l-1]==1,可以看成sum[r]-sum[l-1]>=1,sum[r]-sum[l-1]<=1,于是l-1向r连边1,r向l-1连边-1。

    还有约束条件sum[i]-sum[i-1]>=0,sum[i]-sum[i-1]<=1,于是i-1往i连边0,i往i-1连边1。

    然后跑spfa最短路,有负环输出-1,就过了...等会去补个DP做法嘿嘿

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. #include<queue>
  6. #define ll long long
  7. using namespace std;
  8. const int maxn=,inf=1e9;
  9. struct zs{ll dis,pre,too;}e[maxn];
  10. struct poi{ll pos,dis;};
  11. priority_queue<poi>q;
  12. bool operator <(poi a,poi b){return a.dis>b.dis;};
  13. ll to,i,now,n,m,s,t,x,y,z,tot,last[maxn],dis[maxn],mn,mx,ans;
  14. bool v[maxn],flag;
  15. void read(ll &k)
  16. {
  17. int f=;k=;char c=getchar();
  18. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  19. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  20. k*=f;
  21. }
  22. void add(int x,int y,int z){e[++tot].too=y;e[tot].dis=z;e[tot].pre=last[x];last[x]=tot;}
  23. void spfa(int x)
  24. {
  25. memset(dis,,(n+)<<);dis[x]=;q.push((poi){x,});v[x]=;
  26. while(!q.empty())
  27. {
  28. for(to=e[i=last[now=q.top().pos]].too,q.pop();i;to=e[i=e[i].pre].too)
  29. if(dis[to]>dis[now]+e[i].dis)
  30. {
  31. ans++;
  32. if(ans>){printf("-1");flag=;return;}
  33. dis[to]=dis[now]+e[i].dis;
  34. if(!v[to])v[to]=,q.push((poi){to,dis[to]});
  35. }
  36. v[now]=;
  37. }
  38. }
  39. int main()
  40. {
  41. read(n);read(m);
  42. flag=;
  43. for(int i=;i<=m;i++)
  44. {
  45. read(x);read(y);
  46. add(x-,y,);add(y,x-,-);;
  47. }
  48. mn=;mx=n;
  49. for(int i=mn;i<mx;i++)add(i,i+,),add(i+,i,);
  50. spfa(mn);
  51. if(!flag)printf("%lld\n",dis[mx]);
  52. return ;
  53. }

    写了线段树+DP反而慢了QAQ

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. int n,m,z,ans;
  13. int l[maxn],r[maxn],a[maxn<<],x[maxn],y[maxn];
  14. inline void read(int &k)
  15. {
  16. int f=;k=;char c=getchar();
  17. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  18. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  19. k*=f;
  20. }
  21. inline void update(int x,int l,int r,int cx,int delta)
  22. {
  23. if(l==cx&&r==cx){a[x]=delta;return;}
  24. int mid=(l+r)>>;
  25. if(cx<=mid)update(x<<,l,mid,cx,delta);
  26. if(cx>mid)update(x<<|,mid+,r,cx,delta);
  27. a[x]=max(a[x<<],a[x<<|]);
  28. }
  29. inline int query(int x,int l,int r,int cl,int cr)
  30. {
  31. if(cl<=l&&r<=cr)return a[x];
  32. int mid=(l+r)>>,ret=-inf;
  33. if(cl<=mid)ret=max(ret,query(x<<,l,mid,cl,cr));
  34. if(cr>mid)ret=max(ret,query(x<<|,mid+,r,cl,cr));
  35. return ret;
  36. }
  37. int main()
  38. {
  39. read(n);read(m);
  40. for(int i=;i<=n;i++)r[i]=i-;
  41. for(int i=;i<=m;i++)
  42. {
  43. read(x[i]);read(y[i]);
  44. l[y[i]+]=max(l[y[i]+],x[i]);
  45. r[y[i]]=min(r[y[i]],x[i]-);
  46. }
  47. for(int i=;i<=n;i++)l[i]=max(l[i],l[i-]);
  48. for(int i=n-;i;i--)r[i]=min(r[i],r[i+]);
  49. for(int i=;i<=n;i++)
  50. {
  51. int sum=l[i]<=r[i]?query(,,n,l[i],r[i])+:-inf;ans=max(ans,sum);
  52. update(,,n,i,sum);
  53. }
  54. for(int i=;i<=m;i++)if(query(,,n,x[i],y[i])<=){puts("-1");return ;}
  55. printf("%d\n",ans);
  56. return ;
  57. }

  bzoj3048: [Usaco2013 Jan]Cow Lineup

    离散化后标尺法(两个指针l和r),保证区间数字种类<=k+1,用最大值更新答案。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. int n,N,k,l,r,cnt,ans;
  13. int a[maxn],b[maxn],cntt[maxn];
  14. void read(int &k)
  15. {
  16. int f=;k=;char c=getchar();
  17. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  18. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  19. k*=f;
  20. }
  21. int main()
  22. {
  23. read(n);read(k);
  24. for(int i=;i<=n;i++)read(a[i]),b[i]=a[i];N=n;
  25. sort(b+,b++N);N=unique(b+,b++N)-b-;
  26. for(int i=;i<=n;i++)a[i]=lower_bound(b+,b++N,a[i])-b;
  27. l=;r=;cnt=;
  28. while(r<n)
  29. {
  30. r++;
  31. if(!cntt[a[r]])cnt++;
  32. cntt[a[r]]++;
  33. if(cnt>k+)
  34. {
  35. while(cntt[a[l]]!=)cntt[a[l]]--,l++;
  36. cntt[a[l]]=;l++;
  37. cnt--;
  38. }
  39. if(cntt[a[r]]>ans)ans=cntt[a[r]];
  40. }
  41. printf("%d\n",ans);
  42. return ;
  43. }

  bzoj2197: [Usaco2011 Mar]Tree Decoration

    久违的金组水题...(MDZZ以后只要空间苟一律开long longQAQ

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. #define ll long long
  6. using namespace std;
  7. const int maxn=,inf=1e9;
  8. struct poi{int too,pre;}e[maxn];
  9. ll n,fa,mn,tot;
  10. ll ans;
  11. ll c[maxn],nowc[maxn],t[maxn],last[maxn];
  12. void read(ll &k)
  13. {
  14. int f=;k=;char c=getchar();
  15. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  16. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  17. k*=f;
  18. }
  19. void add(int x,int y){e[++tot].too=y;e[tot].pre=last[x];last[x]=tot;}
  20. int dfs(int x)
  21. {
  22. int mn=t[x];
  23. for(int i=last[x];i;i=e[i].pre)
  24. mn=min(dfs(e[i].too),mn),nowc[x]-=c[e[i].too];
  25. if(nowc[x]>)ans+=1ll*nowc[x]*mn;else c[x]-=nowc[x];
  26. return mn;
  27. }
  28. int main()
  29. {
  30. read(n);
  31. for(int i=;i<=n;i++)
  32. {
  33. read(fa);read(c[i]);read(t[i]);nowc[i]=c[i];
  34. if(i!=)add(fa,i);
  35. }
  36. dfs();
  37. printf("%lld\n",ans);
  38. }

  bzoj3407: [Usaco2009 Oct]Bessie's Weight Problem 贝茜的体重问题

    水题一道就够了怎么来两道啊QAQ

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. int n,v,x,y,z,tot;
  13. int f[maxn];
  14. void read(int &k)
  15. {
  16. int f=;k=;char c=getchar();
  17. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  18. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  19. k*=f;
  20. }
  21. int main()
  22. {
  23. read(v);read(n);
  24. for(int i=;i<=n;i++)
  25. {
  26. read(x);
  27. for(int j=v;j>=x;j--)
  28. f[j]=max(f[j],f[j-x]+x);
  29. }
  30. printf("%d\n",f[v]);
  31. return ;
  32. }

  bzoj3887: [Usaco2015 Jan]Grass Cownoisseur

    好题!帮我找出了以前好多的知识漏洞(卡了我好久TAT)

    首先当然是要tarjan缩点。

    预处理1到能到的点记作A集,能到1的点到1记作B集,并bfs求出1到A集,B集到1的最长路,枚举每一条边,如果端点分别是A集和B集,那么就把这条边,反向,两条最长路加起来更新答案。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. struct poi{int x,too,pre;}e[maxn*],e2[maxn*],e3[maxn*];
  13. int n,m,x,y,z,tot,tott,tot2,tot3,top,color,ans;
  14. int len1[maxn],len2[maxn],dfn[maxn],low[maxn],st[maxn],lack[maxn],col[maxn],num[maxn],last[maxn],last2[maxn],last3[maxn],v[maxn],h[maxn];
  15. void read(int &k)
  16. {
  17. int f=;k=;char c=getchar();
  18. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  19. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  20. k*=f;
  21. }
  22. void add(int x,int y){e[++tot].x=x;e[tot].too=y;e[tot].pre=last[x];last[x]=tot;}
  23. void add2(int x,int y){e2[++tot2].x=x;e2[tot2].too=y;e2[tot2].pre=last2[x];last2[x]=tot2;}
  24. void add3(int x,int y){e3[++tot3].x=x;e3[tot3].too=y;e3[tot3].pre=last3[x];last3[x]=tot3;}
  25. void tarjan(int x)
  26. {
  27. dfn[x]=low[x]=++tott;st[++top]=x;lack[x]=top;
  28. for(int i=last[x],too=e[i].too;i;i=e[i].pre,too=e[i].too)
  29. if(!dfn[too])tarjan(too),low[x]=min(low[x],low[too]);
  30. else if(!col[too])low[x]=min(low[x],dfn[too]);
  31. if(dfn[x]==low[x])for(color++;top>=lack[x];top--)col[st[top]]=color,num[color]++;
  32. }
  33. void dfs1(int x)
  34. {
  35. v[x]=;
  36. for(int i=last2[x],too=e2[i].too;i;i=e2[i].pre,too=e2[i].too)dfs1(too);
  37. }
  38. void dfs2(int x)
  39. {
  40. v[x]=;
  41. for(int i=last3[x],too=e3[i].too;i;i=e3[i].pre,too=e3[i].too)dfs2(too);
  42. }
  43. void bfs1()
  44. {
  45. top=;
  46. int front=,rear=;h[]=col[];len1[col[]]=num[col[]];
  47. while(front!=rear)
  48. {
  49. int now=h[++front];if(front==maxn)front=-;
  50. for(int i=last2[now];i;i=e2[i].pre)
  51. {
  52. h[++rear]=e2[i].too;if(rear==maxn)rear=-;
  53. len1[e2[i].too]=max(len1[e2[i].too],len1[now]+num[e2[i].too]);
  54. }
  55. }
  56. }
  57. void bfs2()
  58. {
  59. top=;
  60. int front=,rear=;h[]=col[];len2[col[]]=num[col[]];
  61. while(front!=rear)
  62. {
  63. int now=h[++front];if(front==maxn)front=-;
  64. for(int i=last3[now];i;i=e3[i].pre)
  65. {
  66. h[++rear]=e3[i].too;if(rear==maxn)rear=-;
  67. len2[e3[i].too]=max(len2[e3[i].too],len2[now]+num[e3[i].too]);
  68. }
  69. }
  70. }
  71. int main()
  72. {
  73. read(n);read(m);
  74. for(int i=;i<=m;i++)read(x),read(y),add(x,y);
  75. for(int i=;i<=n;i++)if(!dfn[i])tarjan(i);
  76. for(int i=;i<=tot;i++)if(col[e[i].x]!=col[e[i].too])add2(col[e[i].x],col[e[i].too]),add3(col[e[i].too],col[e[i].x]);
  77. dfs1(col[]);dfs2(col[]);
  78. bfs1();bfs2();
  79. ans=*num[col[]];
  80. for(int i=;i<=tot2;i++)
  81. {
  82. if((v[e2[i].x]==||e2[i].x==col[])&&(v[e2[i].too]==||e2[i].too==col[]))
  83. ans=max(ans,len2[e2[i].x]+len1[e2[i].too]);
  84. }
  85. printf("%d\n",ans-num[col[]]);
  86. return ;
  87. }

  bzoj1727: [Usaco2006 Open]The Milk Queue 挤奶队列

    不会...知道是贪心但是不会贪...题解好喵喵啊

    直接搬Oakley_的题解好了。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. struct poi{int x,y;}a[maxn];
  13. int n,m,x,y,z,tot;
  14. ll ans,sum,rest;
  15. void read(int &k)
  16. {
  17. int f=;k=;char c=getchar();
  18. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  19. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  20. k*=f;
  21. }
  22. bool cmp(poi a,poi b){return min(a.x,b.y)<min(a.y,b.x);}
  23. int main()
  24. {
  25. read(n);
  26. for(int i=;i<=n;i++)read(a[i].x),read(a[i].y),sum+=a[i].y;
  27. sort(a+,a++n,cmp);
  28. for(int i=;i<=n;i++)
  29. {
  30. if(a[i].x<=rest)rest-=a[i].x;
  31. else ans+=a[i].x-rest,rest=;
  32. rest+=a[i].y;
  33. }
  34. printf("%lld\n",ans+sum);
  35. return ;
  36. }

  bzoj3312: [Usaco2013 Nov]No Change

    看见K<=16就知道要状压DP了...

    f[i]表示硬币状态为i最多能买多少东西。

    f[i]=max(f[i^(1<<(j-1))])+硬币 j 能买接下来的几件东西,二分一波就好了嗯

    又忘记输出-1 WA了一次QAQ

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. int n,k,x,y,z,tot,ans,state;
  13. int coin[maxn],sum[maxn],f[maxn];
  14. void read(int &k)
  15. {
  16. int f=;k=;char c=getchar();
  17. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  18. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  19. k*=f;
  20. }
  21. int main()
  22. {
  23. read(k);read(n);
  24. for(int i=;i<=k;i++)read(coin[i]);
  25. for(int i=;i<=n;i++)read(sum[i]),sum[i]+=sum[i-];
  26. state=(<<k)-;memset(f,-,(state+)<<);
  27. f[]=;
  28. for(int i=;i<=state;i++)
  29. {
  30. for(int j=;j<=k;j++)
  31. if((i&(<<(j-)))==(<<(j-)))
  32. {
  33. int l=f[i^(<<(j-))]+,r=n,summ=sum[l-];
  34. while(l<r)
  35. {
  36. int mid=(l+r+)>>;
  37. if(sum[mid]-summ<=coin[j])l=mid;
  38. else r=mid-;
  39. }
  40. f[i]=max(f[i],l);
  41. }
  42. }
  43. ans=-inf;
  44. for(int i=;i<=state;i++)
  45. {
  46. if(f[i]!=n)continue;
  47. int rest=;
  48. for(int j=;j<=k;j++)
  49. if(!(i&(<<(j-))))rest+=coin[j];
  50. ans=max(ans,rest);
  51. }
  52. printf("%d\n",ans!=-inf?ans:-);
  53. return ;
  54. }

  bzoj2272: [Usaco2011 Feb]Cowlphabet 奶牛文字

    一眼题...因为一个sb错误错了好久(虽然要是没这个错我不会发现自己模数写错两次T_T(1e9+7->987654321->97654321

    f[i][j][k]表示有i个大写字母,j个小写字母,最后一位是k的方案数。注意这个不能和背包一样写。。因为有了那最后一维...

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9,mod=;
  12. int n,u,l,tot,ans;
  13. int f[][][];
  14. char s[][];
  15. void read(int &k)
  16. {
  17. int f=;k=;char c=getchar();
  18. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  19. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  20. k*=f;
  21. }
  22. bool is1(char ch){return (ch<='Z'&&ch>='A');}
  23. bool is2(char ch){return (ch<='z'&&ch>='a');}
  24. int up(int x){return is1(s[x][])+is1(s[x][]);}
  25. int low(int x){return is2(s[x][])+is2(s[x][]);}
  26. int main()
  27. {
  28. read(u);read(l);read(n);
  29. for(int i=;i<=n;i++)scanf("%s",s[i]+);
  30. for(int i=;i<=n;i++)f[up(i)][low(i)][s[i][]]++;
  31. for(int j=;j<=u;j++)
  32. for(int k=;k<=l;k++)
  33. if(j+k>)
  34. for(int i=;i<=n;i++)
  35. {
  36. if(j<is1(s[i][])||k<is2(s[i][]))continue;
  37. f[j][k][s[i][]]+=f[j-is1(s[i][])][k-is2(s[i][])][s[i][]];
  38. f[j][k][s[i][]]>=mod&&(f[j][k][s[i][]]-=mod);
  39. }
  40. for(int j=;j<=;j++)
  41. ans+=f[u][l]['a'+j],ans>=mod&&(ans-=mod),ans+=f[u][l]['A'+j],ans>=mod&&(ans-=mod);
  42. printf("%d\n",ans);
  43. return ;
  44. }

  bzoj1750: [Usaco2005 qua]Apple Catching

    一眼题*2....f[i][j][0/1]表示第i分钟,走了j次,在第1/2棵树下的最大收益

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. int n,w,x,y,z,tot,ans;
  13. int f[][][],a[];
  14. void read(int &k)
  15. {
  16. int f=;k=;char c=getchar();
  17. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  18. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  19. k*=f;
  20. }
  21. int main()
  22. {
  23. read(n);read(w);
  24. for(int i=;i<=n;i++)read(a[i]);
  25. for(int i=;i<=n;i++)
  26. {
  27. f[i][][]=f[i-][][]+(a[i]==);
  28. f[i][][]=f[i-][][]+(a[i]==);
  29. ans=max(ans,max(f[i][][],f[i][][]));
  30. for(int j=;j<=min(i,w);j++)
  31. {
  32. f[i][j][]=max(f[i-][j][],f[i-][j-][])+(a[i]==);
  33. f[i][j][]=max(f[i-][j][],f[i-][j-][])+(a[i]==);
  34. ans=max(ans,max(f[i][j][],f[i][j][]));
  35. }
  36. }
  37. printf("%d\n",ans);
  38. return ;
  39. }

  bzoj1736: [Usaco2005 jan]The Wedding Juicer 婚宴的榨汁机

    从四周向中间宽搜,每次出队高度最小的点,并记录来的路上的最大值,拿这个最大值减去当前高度,求和就是答案了。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9,dx[]={,,,-},dy[]={,,-,};
  12. struct poi{int x,y,h;};
  13. priority_queue<poi>q;
  14. bool operator<(poi a,poi b){return a.h>b.h;}
  15. int n,m,x,y,z,tot;
  16. int h[maxn][maxn];
  17. bool v[maxn][maxn];
  18. ll ans;
  19. void read(int &k)
  20. {
  21. int f=;k=;char c=getchar();
  22. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  23. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  24. k*=f;
  25. }
  26. void bfs()
  27. {
  28. while(!q.empty())
  29. {
  30. poi now=q.top();q.pop();
  31. for(int i=;i<;i++)
  32. {
  33. int xx=now.x+dx[i],yy=now.y+dy[i];
  34. if(xx<||xx>n||yy<||yy>m||v[xx][yy])continue;
  35. if(h[xx][yy]<now.h)
  36. {
  37. ans+=now.h-h[xx][yy];
  38. h[xx][yy]=now.h;
  39. }
  40. v[xx][yy]=;q.push((poi){xx,yy,h[xx][yy]});
  41. }
  42. }
  43. }
  44. int main()
  45. {
  46. read(m);read(n);
  47. for(int i=;i<=n;i++)
  48. for(int j=;j<=m;j++)
  49. read(h[i][j]);
  50. for(int i=;i<=m;i++)
  51. q.push((poi){,i,h[][i]}),q.push((poi){n,i,h[n][i]}),v[][i]=,v[n][i]=;
  52. for(int i=;i<n;i++)
  53. q.push((poi){i,,h[i][]}),q.push((poi){i,m,h[i][m]}),v[i][]=,v[i][m]=;
  54. bfs();printf("%lld\n",ans);
  55. return ;
  56. }

  bzoj1779: [Usaco2010 Hol]Cowwar 奶牛战争

    刷了几题银组刷不下去了。。还是回来刷金组吧TAT

    看这数据范围完全想不到网络流啊,后来才知道如果容量全部为1的话dinic的效率实际上是O(min(n^(2/3),m^(1/2))*m)...所以能跑过

    四分图。

    源点连所有J,J连所有走一步能到的不是T的点和自己所在的点,这些点拆成i和i',连边,i'和所有相邻的T连边,T和汇点连边,容量都是1,跑最大流。

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<iostream>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<cstdio>
  7. using namespace std;
  8. const int inf=1e9,maxn=;
  9. struct poi{int too,pre,cf;}e[],e2[];
  10. int n,m,tot,tot2,ans,x,y,z,front,rear,sum;
  11. int h[maxn],v[maxn],last[maxn],last2[maxn],dis[maxn],cur[maxn];
  12. char s[maxn];
  13. void read(int &k)
  14. {
  15. int f=;k=;char c=getchar();
  16. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  17. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  18. k*=f;
  19. }
  20. void add(int x,int y)
  21. {
  22. e[++tot].too=y;e[tot].cf=;e[tot].pre=last[x];last[x]=tot;
  23. e[++tot].too=x;e[tot].pre=last[y];last[y]=tot;
  24. }
  25. void add2(int x,int y){e2[++tot2].too=y;e2[tot2].pre=last2[x];last2[x]=tot2;}
  26. bool bfs()
  27. {
  28. for(int i=;i<=sum;i++)v[i]=,dis[i]=-;
  29. dis[]=;v[]=;h[]=;front=;rear=;
  30. while(front!=rear)
  31. {
  32. int now=h[++front];if(front==maxn)front=-;
  33. for(int i=last[now];i;i=e[i].pre)
  34. {
  35. int too=e[i].too;
  36. if((!v[too])&&e[i].cf)
  37. {
  38. dis[too]=dis[now]+;if(too==sum)return ;
  39. v[too]=;h[++rear]=too;if(rear==maxn)rear=-;
  40. }
  41. }
  42. }
  43. return ;
  44. }
  45. int dfs(int x,int f)
  46. {
  47. int flow=,tmp;
  48. if(x==sum)return f;
  49. for(int &i=cur[x];i;i=e[i].pre)
  50. {
  51. int too=e[i].too;
  52. if(dis[too]==dis[x]+&&e[i].cf)
  53. {
  54. tmp=dfs(too,min(f-flow,e[i].cf));
  55. e[i].cf-=tmp;e[i^].cf+=tmp;flow+=tmp;
  56. if(f==flow)return f;
  57. }
  58. }
  59. return flow;
  60. }
  61. void dinic()
  62. {
  63. while(bfs())
  64. {
  65. for(int i=;i<=sum;i++)cur[i]=last[i];
  66. ans+=dfs(,inf);
  67. }
  68. }
  69. int main()
  70. {
  71. tot=;
  72. read(n);read(m);sum=(n<<)+;
  73. scanf("%s",s+);
  74. for(int i=;i<=m;i++)read(x),read(y),add2(x,y),add2(y,x);
  75. for(int i=;i<=n;i++)
  76. {
  77. if(s[i]=='J')
  78. {
  79. add(,i);add(i,i+n);add(i+n,i+(n<<));
  80. for(int j=last2[i],too=e2[j].too;j;j=e2[j].pre,too=e2[j].too)
  81. if(s[too]!='T')add(i,too+n);
  82. }
  83. else if(s[i]!='T')add(i+n,i+(n<<));
  84. if(s[i]=='T')
  85. {
  86. add(i+n*,sum);
  87. for(int j=last2[i],too=e2[j].too;j;j=e2[j].pre,too=e2[j].too)
  88. add(too+(n<<),i+n*);
  89. }
  90. }
  91. dinic();
  92. printf("%d\n",ans);
  93. return ;
  94. }

  bzoj4094: [Usaco2013 Dec]Optimal Milking

    一眼题。。。线段树维护选左边右边,左边,右边,不选的最大值。

    一开始没开long long WA了一发,改完交就AC了,好爽(假·1A

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. struct poi{ll lr,l,r,none;}a[maxn*];
  13. ll n,m,x,y,z,tot;
  14. ll ans;
  15. void read(ll &k)
  16. {
  17. int f=;k=;char c=getchar();
  18. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  19. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  20. k*=f;
  21. }
  22. void pushup(int x,int l,int r)
  23. {
  24. if(l==r)return;
  25. a[x].lr=max(a[x<<].l+a[x<<|].r,max(a[x<<].lr+a[x<<|].r,a[x<<].l+a[x<<|].lr));
  26. a[x].l=max(a[x<<].l+a[x<<|].l,max(a[x<<].l+a[x<<|].none,a[x<<].lr+a[x<<|].none));
  27. a[x].r=max(a[x<<].r+a[x<<|].r,max(a[x<<].none+a[x<<|].r,a[x<<].none+a[x<<|].lr));
  28. a[x].none=max(a[x<<].r+a[x<<|].none,max(a[x<<].none+a[x<<|].l,a[x<<].none+a[x<<|].none));
  29. }
  30. void build(int x,int l,int r)
  31. {
  32. if(l==r){read(a[x].lr);return;}
  33. int mid=(l+r)>>;
  34. build(x<<,l,mid);build(x<<|,mid+,r);
  35. pushup(x,l,r);
  36. }
  37. void update(int x,int l,int r,int cx,int delta)
  38. {
  39. if(l==cx&&r==cx){a[x].lr=delta;return;}
  40. int mid=(l+r)>>;
  41. if(cx<=mid)update(x<<,l,mid,cx,delta);
  42. if(cx>mid)update(x<<|,mid+,r,cx,delta);
  43. pushup(x,l,r);
  44. }
  45. int main()
  46. {
  47. read(n);read(m);build(,,n);
  48. for(int i=;i<=m;i++)
  49. {
  50. read(x);read(y);
  51. update(,,n,x,y);
  52. ans+=max(a[].lr,max(a[].none,max(a[].l,a[].r)));
  53. }
  54. printf("%lld\n",ans);
  55. return ;
  56. }

  bzoj3886: [Usaco2015 Jan]Moovie Mooving

    很早就写了一直懒得写题解....

    状压DP f[i]表示电影的状态为i最多能看多长时间,随便转移

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. int n,m,x,y,z,tot,ans,l,r,mid,L,cnt;
  13. int f[],len[maxn],num[maxn],a[maxn][maxn*];
  14. void read(int &k)
  15. {
  16. int f=;k=;char c=getchar();
  17. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  18. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  19. k*=f;
  20. }
  21. bool check(int i,int x){return a[i][mid]<=x+;}
  22. int main()
  23. {
  24. read(n);read(L);
  25. for(int i=;i<=n;i++)
  26. {
  27. read(len[i]);read(num[i]);
  28. for(int j=;j<=num[i];j++)
  29. read(a[i][j]);
  30. }
  31. memset(f,-,sizeof(f));f[]=;ans=inf;
  32. for(int i=;i<(<<n);i++)
  33. {
  34. cnt=;
  35. for(int j=;j<=n;j++)
  36. if(!(i&(<<(j-))))
  37. {
  38. cnt++;
  39. l=;r=num[j];
  40. while(l<r)
  41. {
  42. mid=(l+r+)>>;
  43. if(check(j,f[i]))l=mid;
  44. else r=mid-;
  45. }
  46. if(!l)continue;
  47. f[i|(<<(j-))]=max(f[i|(<<(j-))],a[j][l]+len[j]);
  48. }
  49. if(f[i]>=L)ans=min(ans,n-cnt);
  50. }
  51. printf("%d\n",ans!=inf?ans:-);
  52. return ;
  53. }

  bzoj1915: [Usaco2010 Open]奶牛的跳格子游戏

    DP+单调队列优化

    f[i]表示去的时候跳到i,回来的时候跳到i-1的最大收益。预处理sum表示所有正数的前缀和(因为一个可以自由跳的区间内负数一定不取

    f[i] =max(f[j] + a[i] + a[i-1] + sum[i-2] - sum[j]) {1<=j<i-1&&i-j<=k)

    每次把f[i-1]-sum[i-1]加入单调队列就行了。

    交了5发因为空间开太大没艹上#1....丢人

    #2也是不错的嘿嘿

    

  bzoj4393: [Usaco2015 Dec]Fruit Feast

    果然新题如果AC人数少就肯定是水题了...

    显然只有四种情况,不喝水,吃A喝水,吃B喝水,吃AB喝水,记得判一下饱涨值够不够吃

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. int n,n1,n2,n3,A,B,a,b,ans;
  13. void read(int &k)
  14. {
  15. int f=;k=;char c=getchar();
  16. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  17. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  18. k*=f;
  19. }
  20. int main()
  21. {
  22. read(n);read(A);read(B);
  23. a=A>>;b=B>>;
  24. n1=n-a;n2=n-b;n3=n-a-b;
  25. for(int i=;i<=n/A;i++)
  26. ans=max(ans,i*A+B*((n-i*A)/B));
  27. if(n>=A)
  28. for(int i=;i<=n1/A;i++)
  29. ans=max(ans,i*A+B*((n1-i*A)/B)+a);
  30. if(n>=B)
  31. for(int i=;i<=n2/A;i++)
  32. ans=max(ans,i*A+B*((n2-i*A)/B)+b);
  33. if(n>=A+B)
  34. for(int i=;i<=n3/A;i++)
  35. ans=max(ans,i*A+B*((n3-i*A)/B)+a+b);
  36. printf("%d\n",ans);
  37. return ;
  38. }

  bzoj4580: [Usaco2016 Open]248

    久违的1A........

    嗯这题又印证了上题题解的第一句话

    区间DP,f[l][r]=max(f[l][r],f[l][k]+1) (f[l][k]==f[k+1][r])

  1. #include<iostream>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. #include<map>
  9. #define ll long long
  10. using namespace std;
  11. const int maxn=,inf=1e9;
  12. int n,m,x,y,z,tot,ans;
  13. int f[][];
  14. void read(int &k)
  15. {
  16. int f=;k=;char c=getchar();
  17. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  18. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  19. k*=f;
  20. }
  21. int main()
  22. {
  23. read(n);
  24. memset(f,-,sizeof(f));
  25. for(int i=;i<=n;i++)read(f[i][i]);
  26. for(int i=;i<=n;i++)
  27. for(int j=;i+j-<=n;j++)
  28. {
  29. int L=j,R=i+j-;
  30. for(int k=L;k<R;k++)
  31. if(f[L][k]==f[k+][R]&&f[L][k]!=-)
  32. f[L][R]=max(f[L][R],f[L][k]+);
  33. ans=max(ans,f[L][R]);
  34. }
  35. printf("%d\n",ans);
  36. return ;
  37. }

  bzoj3939: [Usaco2015 Feb]Cow Hopscotch

    f[i][j]=sigma(f[k][l]) {k<i&&l<j}

    我们让每一次转移都求出相同颜色的方案数,再用总方案数减去就行了。注意是每一次转移都要被总方案数减,否则相当于这条路径上全部都相同,这样的补集是至少有一个不同而不是全都不同。

    显然这个DP方程就是统计一个前缀的和,对每个颜色建一棵线段树动态开点+扫描线就好了。

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. using namespace std;
  6. const int maxn=,inf=1e9,mo=1e9+;
  7. struct poi{int sum;}a[maxn*maxn*];
  8. int n,m,K,cnt,cl,cr,cx;
  9. int col[maxn][maxn],tot[maxn][maxn],sum[maxn][maxn],rt[maxn*maxn*],lt[maxn*maxn*],f[maxn][maxn],root[maxn*maxn*];
  10. void read(int &k)
  11. {
  12. int f=;k=;char c=getchar();
  13. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  14. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  15. k*=f;
  16. }
  17. inline int mod(int x){return x>=mo?x-mo:x;}
  18. void update(int &x,int l,int r,int delta)
  19. {
  20. if(!x)x=++cnt;a[x].sum=mod(a[x].sum+delta);
  21. if(l==r)return;
  22. int mid=(l+r)>>;
  23. if(cx<=mid)update(lt[x],l,mid,delta);
  24. else update(rt[x],mid+,r,delta);
  25. }
  26. int query(int x,int l,int r)
  27. {
  28. if(!x)return ;
  29. if(cl<=l&&r<=cr)return a[x].sum;
  30. int mid=(l+r)>>,ret=;
  31. if(cl<=mid)ret+=query(lt[x],l,mid);
  32. if(cr>mid)ret+=query(rt[x],mid+,r);
  33. ret=mod(ret);return ret;
  34. }
  35. int main()
  36. {
  37. read(n);read(m);read(K);
  38. for(int i=;i<=n;i++)
  39. for(int j=;j<=m;j++)
  40. read(col[i][j]);
  41. sum[][]=f[][]=;
  42. for(int i=;i<=n;i++)
  43. {
  44. for(int j=;j<=m;j++)
  45. {
  46. if(i==&&j==)continue;
  47. cl=,cr=j-;
  48. f[i][j]=mod(sum[i-][j-]+mo-query(root[col[i][j]],,m));
  49. sum[i][j]=(1ll*sum[i][j-]+1ll*sum[i-][j]-1ll*sum[i-][j-]+1ll*f[i][j]+mo)%mo;
  50. }
  51. for(int j=;j<=m;j++)
  52. cx=j,update(root[col[i][j]],,m,f[i][j]);
  53. }
  54. printf("%d\n",f[n][m]);
  55. }

  bzoj1737: [Usaco2005 jan]Naptime 午睡时间

    不考虑环的话则有 f[i][j][1]=max(f[i-1][k][1]+a[j],f[i-1][k][0]){k<j}

             f[i][j][0]=max(f[i-1][k][1],f[i-1][k][0])

             初始状态f[1][1][1]=f[1][0][0]=0;

    对于环多考虑一种跨环的情况,也就是1必须睡觉,强制跨环的话初始状态为f[1][1][1]=0 最后答案为f[n][m][1]+a[1]

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cstdio>
  5. #include<queue>
  6. #include<algorithm>
  7. using namespace std;
  8. const int maxn=,inf=1e9;
  9. int n,m,ans;
  10. int a[maxn],f[][maxn][];
  11. void read(int &k)
  12. {
  13. int f=;k=;char c=getchar();
  14. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  15. while(c<=''&&c>='')k=k*+c-'',c=getchar();
  16. k*=f;
  17. }
  18. int max(int a,int b){return a>b?a:b;}
  19. int main()
  20. {
  21. read(n);read(m);
  22. for(int i=;i<=n;i++)read(a[i]);
  23. memset(f,,sizeof(f));
  24. f[][][]=f[][][]=;
  25. for(int i=;i<=n;i++)
  26. {
  27. for(int j=;j<=m;j++)
  28. {
  29. if(j)f[i&][j][]=max(f[(i&)^][j-][],f[(i&)^][j-][]+a[i]);
  30. f[i&][j][]=max(f[(i&)^][j][],f[(i&)^][j][]);
  31. }
  32. ans=max(ans,max(f[i&][m][],f[i&][m][]));
  33. }
  34. memset(f,,sizeof(f));
  35. f[][][]=;
  36. for(int i=;i<=n;i++)
  37. {
  38. for(int j=;j<=m;j++)
  39. {
  40. if(j)f[i&][j][]=max(f[(i&)^][j-][],f[(i&)^][j-][]+a[i]);
  41. f[i&][j][]=max(f[(i&)^][j][],f[(i&)^][j][]);
  42. }
  43. }
  44. ans=max(ans,f[n&][m][]+a[]);
  45. printf("%d\n",ans);
  46. }

bzoj Usaco补完计划(优先级 Gold>Silver>资格赛)的更多相关文章

  1. [TaskList] 省选前板子补完计划

    省选前本子补完计划 [ ] 带权并查集 [ ] 树上莫队 - UOJ58 [WC2013]糖果公园 loj2485「CEOI2017」Chase

  2. QBXT 2017GoKing problems 补完计划

    10.11 Updata : 烦死了...麻烦死了...不补了..就这些吧 20171001 上: 100 + 90 + 90 = 280 = rank 8 T1 /* T1 从最大的数开始倒着枚举 ...

  3. NodeJS学习:爬虫小探补完计划

    说明:本文在个人博客地址为edwardesire.com,欢迎前来品尝. 书接上回,我们需要修改程序以达到连续抓取40个页面的内容.也就是说我们需要输出每篇文章的标题.链接.第一条评论.评论用户和论坛 ...

  4. CodeVS1169 传纸条 [DP补完计划]

    题目传送门 题目描述 Description 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端, ...

  5. NLP 开源形近字算法补完计划(完结篇)

    前言 所有的故事都有开始,也终将结束. 本文将作为 NLP 汉字相似度的完结篇,为该系列画上一个句号. 起-NLP 中文形近字相似度计算思路 承-中文形近字相似度算法实现,为汉字 NLP 尽一点绵薄之 ...

  6. 洛谷P2224 [HNOI2001] 产品加工 [DP补完计划,背包]

    题目传送门 产品加工 题目描述 某加工厂有A.B两台机器,来加工的产品可以由其中任何一台机器完成,或者两台机器共同完成.由于受到机器性能和产品特性的限制,不同的机器加工同一产品所需的时间会不同,若同时 ...

  7. POJ1742 Coin [DP补完计划]

    题目传送门 Coins Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 41707   Accepted: 14125 Des ...

  8. 洛谷P1280 尼克的任务 [DP补完计划]

    题目传送门 题目描述 尼克每天上班之前都连接上英特网,接收他的上司发来的邮件,这些邮件包含了尼克主管的部门当天要完成的全部任务,每个任务由一个开始时刻与一个持续时间构成. 尼克的一个工作日为N分钟,从 ...

  9. SDWC补题计划

    2018的寒假去了SD的冬令营,因为一班二班难度悬殊,对我很不友好,几乎什么也没学会,但是我把两个班的课件都存了下来,现在慢慢把两个班的例题以及课后题都补一补(毕竟冬令营的钱不能白花). 这些题目横跨 ...

随机推荐

  1. Qt-LCD电子时钟

    先上效果图吧 就是这个样子,简单的时间显示时间. 这里需要注意的是,我们最好建立一个空文件,这里我们需要建立一个集成QLCDNumber的类 具体方法如下图 一下是源代码 digiclock.h #i ...

  2. 了解Python控制流语句——if语句

    控制流 截止到现在,在我们所看过的程序中,总是有一系列语句从上到下精确排列,并交由 Python 忠实地执行.如果你想改变这一工作流程,应该怎么做?就像这样的情况:你需要程序作出一些决定,并依据不同的 ...

  3. js写的数码时钟,在“最小化”浏览器 或者 “切换网页”是动画效果好像不对

    一.问题 在“最小化”浏览器 或者 “切换网页”是动画效果不对,不知道哪里出了问题???是不是”最小化“时网页定时器关掉了,还是其他什么原因啊 ???? 二.HTML代码如下 <div id=& ...

  4. 数据库Mysql的学习(七)-自定义函数和流程控制

    DELIMITER // (设置结束符 其实我也不太明白为啥要这样 记住就行把) CREATE FUNCTION ym_date(mydate DATE) (创建函数 函数名字(参数)) ) (指定函 ...

  5. [CH0304]IncDec Sequence

    和NOIP2018DAY1T1类似的题目,但思维难度高多了. 这题既可以抬高路面,也可以降低路面,而且目标平面不确定,就难起来了. 但是两道题的基本思路几乎一样,同样我们将 2~n 的高度差分,1之所 ...

  6. C++clock()延时循环

    函数clock(),返回程序开始执行后所用的系统时间,但是有两个复制问题. 1.clock()返回时间的单位不一定是秒 2.该函数的返回类型在某些系统上可能是Long,也可能是unsigned lon ...

  7. vector:动态数组

    vector是C++标准模板库中的部分内容,中文偶尔译作“容器”,但并不准确.它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库.vector之所以被认为是一个容器,是因为它能够像容器一样存 ...

  8. Hadoop第二课:Hadoop集群环境配置

    一.Yum配置 1.检查Yum是否安装 rpm -qa|grep yum 2.修改yum源,我使用的是163的镜像源(http://mirrors.163.com/),根据自己的系统选择源, #进入目 ...

  9. SGU 326 Perspective(最大流)

    Description Breaking news! A Russian billionaire has bought a yet undisclosed NBA team. He's plannin ...

  10. 手机站测试工具(node服务器)

    最近在工作中遇到手机站测试的问题,于是就写了一个node服务外加一个第三方的转二维码功能,欢迎拍砖~ 项目地址:https://github.com/finderL/webserver