我好菜啊都不会

T1.boats

题目大意:给你N段区间,按顺序决定每段区间可以选一个数或不选,若选则选的这个数必须大于所有在这之前选的数,求有多少种方案。(N<=500,区间在[1,1e9]范围内)

思路:我的做法比较奇怪……根据DP的思路,题目可以转化为一个数列一开始0的位置是1其他都是0,然后每次把一个区间里的数全部变成原来数列的前缀和,然后我按权值分了个块,把区间左右端点离散后如果相邻的差超过k就分成相差不超过k的几块,预处理出一开始都为1的各个长度的区间经过若干次前缀和后和为多少,我们就可以把一个区间的和表示成有几种初始值,每种进行若干次前缀和后的总和,每次操作把一个新的值插入离散出来的区间里,利用预处理的信息算答案(有点难说清楚,感兴趣的参见代码实现……),复杂度O(kn+(1e9/k+n)*n^2),k为块大小,子任务制得分58/100(最后一个T),后来发现多次前缀和就是组合数,于是复杂度变成O(k+(1e9/k+n)*n^2),好像就能过了。

暴力算前缀和

  1. #include<cstdio>
  2. #include<algorithm>
  3. using namespace std;
  4. inline int read()
  5. {
  6. int x;char c;
  7. while((c=getchar())<''||c>'');
  8. for(x=c-'';(c=getchar())>=''&&c<='';)x=(x<<)+(x<<)+c-'';
  9. return x;
  10. }
  11. #define MN 500
  12. #define MC 11000
  13. #define K 100000
  14. #define MOD 1000000007
  15. int l[MN+],r[MN+],c[MC+],cn;
  16. int f[MN+][K+],s[MC+],t[MC+],p[MC+][MN+];
  17. inline int mod(int x){return x>=MOD?x-MOD:x;}
  18. int main()
  19. {
  20. int n=read(),i,j,k,x,v;
  21. for(i=;i<=K;++i)f[][i]=i;
  22. for(i=;i<=n;++i)for(j=;j<=K;j+=)
  23. f[i][j ]=mod(f[i][j-]+f[i-][j ]),
  24. f[i][j+]=mod(f[i][j ]+f[i-][j+]),
  25. f[i][j+]=mod(f[i][j+]+f[i-][j+]),
  26. f[i][j+]=mod(f[i][j+]+f[i-][j+]);
  27. for(i=;i<=n;++i)c[++cn]=l[i]=read()-,c[++cn]=r[i]=read();
  28. sort(c+,c+cn+);
  29. for(i=,j=;i<=cn;++i)if(c[i]!=c[j])c[++j]=c[i];cn=j;
  30. for(i=,j=cn;i<j;++i)for(k=c[i];c[i+]-k>K;)c[++cn]=k+=K;
  31. sort(c+,c+cn+);
  32. for(i=;i<=n;++i)for(j=x=;j<=cn;++j)
  33. if(c[j-]>=l[i]&&c[j]<=r[i])
  34. {
  35. p[j][t[j]++]=x;x=mod(x+s[j]);v=c[j]-c[j-];
  36. for(k=s[j]=;k<t[j];++k)
  37. s[j]=(s[j]+1ll*p[j][k]*f[t[j]-k][v])%MOD;
  38. }
  39. else x=mod(x+s[j]);
  40. for(i=,x=;i<=cn;++i)x=mod(x+s[i]);
  41. printf("%d",x);
  42. }

组合数

  1. #include<cstdio>
  2. #include<algorithm>
  3. using namespace std;
  4. inline int read()
  5. {
  6. int x;char c;
  7. while((c=getchar())<''||c>'');
  8. for(x=c-'';(c=getchar())>=''&&c<='';)x=(x<<)+(x<<)+c-'';
  9. return x;
  10. }
  11. #define MN 500
  12. #define MC 1100
  13. #define K 10000000
  14. #define MOD 1000000007
  15. int l[MN+],r[MN+],c[MC+],cn;
  16. int f[K*+],vf[K*+],s[MC+],t[MC+],p[MC+][MN+];
  17. inline int mod(int x){return x>=MOD?x-MOD:x;}
  18. inline int inv(int x)
  19. {
  20. int r=,y=MOD-;
  21. for(;y;y>>=,x=1LL*x*x%MOD)if(y&)r=1LL*r*x%MOD;
  22. return r;
  23. }
  24. int main()
  25. {
  26. int n=read(),i,j,k,x,v;
  27. for(i=f[]=;i<=K<<;++i)f[i]=1LL*f[i-]*i%MOD;
  28. for(vf[i=K<<]=inv(f[K<<]);i--;)vf[i]=1LL*vf[i+]*(i+)%MOD;
  29. for(i=;i<=n;++i)c[++cn]=l[i]=read()-,c[++cn]=r[i]=read();
  30. sort(c+,c+cn+);
  31. for(i=,j=;i<=cn;++i)if(c[i]!=c[j])c[++j]=c[i];cn=j;
  32. for(i=,j=cn;i<j;++i)for(k=c[i];c[i+]-k>K;)c[++cn]=k+=K;
  33. sort(c+,c+cn+);
  34. for(i=;i<=n;++i)for(j=x=;j<=cn;++j)
  35. if(c[j-]>=l[i]&&c[j]<=r[i])
  36. {
  37. p[j][t[j]++]=x;x=mod(x+s[j]);v=c[j]-c[j-];
  38. for(k=s[j]=;k<t[j];++k)
  39. s[j]=(s[j]+1LL*p[j][k]*f[t[j]-k+v-]%MOD*vf[t[j]-k]%MOD*vf[v-])%MOD;
  40. }
  41. else x=mod(x+s[j]);
  42. for(i=,x=;i<=cn;++i)x=mod(x+s[i]);
  43. printf("%d",x);
  44. }

T2.fireworks

题目大意:给出一棵带边权的树,调整树上边长的消耗是调整后的减去调整前的绝对值,求使根节点到所有叶节点距离相等的最小花费,边长必须大等0。(叶节点个数M<=300,000,每个非叶节点除连向父亲外至少连2条边)

思路:不会,打了个中位数乱贪心,好像会把边权弄成负的所以挂了,捆绑测试只有7分……

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<vector>
  4. #include<iostream>
  5. using namespace std;
  6. #define ll long long
  7. inline int read()
  8. {
  9. int x=;char c;
  10. while((c=getchar())<''||c>'');
  11. for(;c>=''&&c<='';c=getchar())x=(x<<)+(x<<)+c-'';
  12. return x;
  13. }
  14. #define MN 300000
  15. struct edge{int nx,t,w;}e[MN*+];
  16. int n,h[MN+],en;
  17. ll f[MN+],l[MN+],r[MN+];
  18. vector<ll> v[MN+];
  19. inline void ins(int x,int y,int w)
  20. {
  21. e[++en]=(edge){h[x],y,w};h[x]=en;
  22. e[++en]=(edge){h[y],x,w};h[y]=en;
  23. }
  24. inline ll z(ll x){return x<?-x:x;}
  25. void dp(int x,int fa)
  26. {
  27. if(x>n)return;
  28. for(int i=h[x];i;i=e[i].nx)if(e[i].t!=fa)
  29. {
  30. dp(e[i].t,x);
  31. f[x]+=f[e[i].t];
  32. v[x].push_back(l[e[i].t]+e[i].w);
  33. v[x].push_back(r[e[i].t]+e[i].w);
  34. f[x]-=r[e[i].t]-l[e[i].t];
  35. }
  36. sort(v[x].begin(),v[x].end());
  37. l[x]=v[x][v[x].size()/-];r[x]=v[x][v[x].size()/];
  38. for(int i=;i<v[x].size();++i)f[x]+=z(l[x]-v[x][i]);
  39. }
  40. int main()
  41. {
  42. int m,i,x;
  43. n=read();m=read();
  44. for(i=;i<=n+m;++i)x=read(),ins(x,i,read());
  45. dp(,);
  46. cout<<f[]/;
  47. }

正解:用f[i][j]表示子树i内所有叶节点到i距离为j的最小花费,则易知每个f[i]均为下凸函数且可以由各儿子的f合并得到,f[i]具有以下性质:1.f[i][0]=子树i内边权和;2.f[i][0]处函数斜率为负的子树内叶节点个数;3.j足够大时f[i][j]斜率为1。这样我们只要知道f[i][0]之后何时函数斜率增大即可表示这个函数,我们可以记下每个拐点,每个拐点表示在这个点函数斜率增加1(拐点可重),这样儿子的f相加直接把所有拐点合并即可。儿子的f并入父亲的f前先要考虑连到父亲的这条边对儿子的f的影响,分各类情况讨论,我们有:假设凸包H(x)最小值在L~R处取到,这条边长为w,新凸包为H’(x),则:x<=L时,H’(x)=H(x)+w;L<=x<=L+w时,H’(x)=H(L)+w-(x-L);L+w<=x<=R+w时,H’(x)=H(L);R+w<=x时,H’(x)=H(L)+(x-R)-w。即每次我们删掉拐点L和拐点R,并加入拐点L+w和R+w,然后删掉所有使斜率大于1的拐点即可。用可并堆维护拐点,最后把堆中元素全部取出计算答案,复杂度O(MlogM)。

  1. #include<cstdio>
  2. #include<algorithm>
  3. using namespace std;
  4. #define ll long long
  5. inline int read()
  6. {
  7. int x;char c;
  8. while((c=getchar())<''||c>'');
  9. for(x=c-'';(c=getchar())>=''&&c<='';)x=(x<<)+(x<<)+c-'';
  10. return x;
  11. }
  12. #define MN 600000
  13. int fa[MN+],w[MN+],r[MN+],cnt;
  14. ll p[MN*+];
  15. struct heap
  16. {
  17. heap*l,*r;ll p;int d;
  18. heap(ll p):p(p){l=r=;d=;}
  19. friend inline int dis(heap*a){return a?a->d:;}
  20. friend heap*merge(heap*a,heap*b)
  21. {
  22. if(!a)return b;if(!b)return a;
  23. if(a->p<b->p)swap(a,b);
  24. a->r=merge(a->r,b);
  25. if(dis(a->l)<dis(a->r))swap(a->l,a->r);
  26. a->d=dis(a->r)+;
  27. return a;
  28. }
  29. }*rt[MN+];
  30. int main()
  31. {
  32. int n,m,i,j;ll a,b,s=;
  33. n=read();n+=m=read();
  34. for(i=;i<=n;++i)++r[fa[i]=read()],s+=w[i]=read();
  35. for(i=n;i>;--i)
  36. {
  37. if(!rt[i])rt[i]=new heap();
  38. for(j=a=;j<=r[i];++j)
  39. {
  40. if(j<r[i])a=rt[i]->p;
  41. else b=rt[i]->p;
  42. rt[i]=merge(rt[i]->l,rt[i]->r);
  43. }
  44. rt[fa[i]]=merge(rt[fa[i]],merge(rt[i],merge(new heap(a+w[i]),new heap(b+w[i]))));
  45. }
  46. while(rt[])p[++cnt]=rt[]->p,rt[]=merge(rt[]->l,rt[]->r);
  47. for(i=cnt;m;--m,--i)s-=m*(p[i]-p[i+]);
  48. printf("%lld",s);
  49. }

T3.gap

题目大意:交互题,有一个N个数的上升序列,不具体给出序列,仅支持一个操作:MinMax(l,r),会给你数值大小在[l,r]内的序列中元素的最大值和最小值,要求你求出序列中相邻元素的最大差。subtask1:每次MinMax的代价为1,使用的代价不得超过(N+1)/2;subtask2:每次MinMax的代价为[l,r]间元素个数加1,使用的代价不得超过3N。(N<=100,000,序列中元素在[0,1e18]内)

思路:我只会subtask1,先询问[0,1e18],得出最小值x最大值y,再询问[x+1,y-1],以此类推,就能(N+1)/2次询问得出整个序列,得分30/100。subtask2做法:先询问[0,1e18],得出最大最小值,则答案必然不小于(max-min)/(n-1),我们在[min+1,max-1]内每(max-min)/(n-1)分一块,显然块内不存在答案,答案只可能是每一块的最大值与下一块最小值的差分,于是每一块询问一次就可以了,简单的计算后知道这么做最大的代价是3N-1。

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include"gap.h"
  4. #define ll long long
  5. using namespace std;
  6. #define MN 100000
  7. #define INF 1e18
  8. ll a[MN+];
  9. ll find1(int n)
  10. {
  11. ll l=,r=INF;int i,j;
  12. for(i=,j=n;i<=j;l=a[i++]+,r=a[j--]-)MinMax(l,r,a+i,a+j);
  13. for(i=,r=;i<n;++i)r=max(r,a[i+]-a[i]);
  14. return r;
  15. }
  16. ll findGap(int t,int n)
  17. {
  18. if(t==)return find1(n);
  19. ll p,i;int cnt=;
  20. MinMax(,INF,a+,a);
  21. p=(a[]-a[]+n-)/(n-);
  22. for(i=a[];i<a[]-;i+=p)
  23. {
  24. MinMax(i+,min(i+p,a[]-),a+cnt+,a+cnt+);
  25. if(a[cnt+]>)if(++cnt,a[cnt+]!=a[cnt])++cnt;
  26. }
  27. a[++cnt]=a[];
  28. for(i=;i<cnt;++i)p=max(p,a[i+]-a[i]);
  29. return p;
  30. }

APIO 2016的更多相关文章

  1. GDOI 2016 & APIO 2016 游记

    缓慢施工中...... UPD:APIO游记已烂尾......因为Cu滚粗+生病一直没心情写..过了几天就发现APIO的事都快忘光了...去看KPM的就可以啦 今年apio竟然没和gdoi撞...智障 ...

  2. [APIO 2016]Gap

    Description 题库链接 给你一个长度为 \(N\) 的单调递增序列 \(A\) .交互时允许你调用 MinMax(s, t, &mn, &mx) 函数,表示序列元素的值在 \ ...

  3. 【UOJ #205】【APIO 2016】Fireworks

    http://uoj.ac/problem/205 好神的题啊. dp[i][j]表示以i为根的子树调整成长度j需要的最小代价. 首先要观察到dp值是一个下凸壳. 因为从儿子合并到父亲时要把所有儿子的 ...

  4. 【UOJ #206】【APIO 2016】Gap

    http://uoj.ac/problem/206 对于T=1,直接从两端往中间跳可以遍历所有的点. 对于T=2,先求出最小值a和最大值b,由鸽巢原理,答案一定不小于\(\frac{b-a}{N-1} ...

  5. 【UOJ #204】【APIO 2016】Boat

    http://uoj.ac/problem/204 肯定要离散化的,先离散化出\(O(n)\)个取值区间. 设\(f(i,j)\)表示第\(i\)所学校派出的划艇数量在\(j\)区间中. \(f(i, ...

  6. Solution -「APIO 2016」「洛谷 P3643」划艇

    \(\mathcal{Description}\)   Link & 双倍经验.   给定 \(n\) 个区间 \([a_i,b_i)\)(注意原题是闭区间,这里只为方便后文描述),求 \(\ ...

  7. Solution -「ARC 104E」Random LIS

    \(\mathcal{Description}\)   Link.   给定整数序列 \(\{a_n\}\),对于整数序列 \(\{b_n\}\),\(b_i\) 在 \([1,a_i]\) 中等概率 ...

  8. Be Better:遇见更好的自己-2016年记

    其实并不能找到好的词语来形容过去的一年,感觉就如此平淡的过了!没有了毕业的稚气,看事情淡了,少了一丝浮躁,多了一分认真.2016也许就是那句话-多读书,多看报,少吃零食多睡觉,而我更愿意说--Be B ...

  9. Connect() 2016 大会的主题 ---微软大法好

    文章首发于微信公众号"dotnet跨平台",欢迎关注,可以扫页面左面的二维码. 今年 Connect 大会的主题是 Big possibilities. Bold technolo ...

随机推荐

  1. 201621123060《JAVA程序设计》第二周学习总结

    1.本周学习总结 本周学习了JAVA中的引用类.包装类(学习了一种语法:自动装箱)和数组(遍历数组的新方法foreach循环). 2. 书面作业 1.String-使用Eclipse关联jdk源代码 ...

  2. 2017-2018-1 1623 bug终结者 冲刺003

    bug终结者 冲刺003 by 王旌含 今日任务:优化界面布局,提供图片素材 需求 app图标.主界面图.主界面中按钮图:选择关卡图.关卡按键图:游戏中的小人.箱子.地板.墙.目的地:方向按钮:重置按 ...

  3. Exception in thread "main" expected '<document start>', but found BlockMappingStart in 'reader', line 23, column 2: nimbus.host: "master"

    平台:centos-6.3-i386 jdk-7u51 storm 0.9.1 python 2.6.6   hadoop 1.2.1 启动storm的时候,遇到这个问题,百度之后,看到大家的解决方案 ...

  4. [Android FrameWork 6.0源码学习] View的重绘过程之WindowManager的addView方法

    博客首页:http://www.cnblogs.com/kezhuang/p/关于Activity的contentView的构建过程,我在我的博客中已经分析过了,不了解的可以去看一下<[Andr ...

  5. 微信支付get_brand_wcpay_request:fail

    最近做了微信支付功能,和后端一起踩坑中,微信一直报错:get_brand_wcpay_request:fail 出现该问题的原因: 1.生成的sign签名有问题 2.支付授权目录配置有问题 在经过仔细 ...

  6. js定时刷新页面.

    //页面定时刷新.2017.09.27 $(document).ready(function () { self.setInterval(function () { var d = new Date( ...

  7. Column Addition~DP(脑子抽了,当时没有想到)

    Description A multi-digit column addition is a formula on adding two integers written like this:

  8. 新概念英语(1-137)A pleasant dream

    Lesson 137 A pleasant dream 美好的梦 Listen to the tape then answer this question. What would Julie like ...

  9. 新概念英语(1-63)Thank you, doctor.

    新概念英语(1-63)Thank you, doctor. Who else is in bed today? why? A:How's Jimmy today? B:Better. Thank yo ...

  10. global文件中的application_start方法中做: 定时器

    <%@ Application Language="C#" %> <%@ import Namespace="System.Data" %&g ...