2016的题貌似是韩国棒子出的,好丧啊.... 看了题解还想了好久......

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

A.Boat

有n个数,每个数字可取[li,ri]内的任意整数si,但是要求对于任意i<j,都有si<sj,求方案数  n<=500,l,r<=10^9

题解:首先离散,然后不同区间的方案数很好转移,我们考虑相同区间的方案数,发现是一个差分了多次的数列,如果区间长度是l,选m个这样的区间,那么方案数是11111...差分m次后的第l项。然后我们可以发现这个其实是一个组合数,等于C(m,m+l)。我们用f[i][j]表示第i个选第j个区间的方案数,然后我们把f数组前缀和之后推出公式,

f[i][j]=∑C(i-i'-1,i-i'+l-1) * f[i'-1][j-1]

复杂度n^3

#include<iostream>
#include<cstdio>
#include<algorithm>
#define mod 1000000007
#define MAXN 1000
#define int long long
using namespace std;
inline int read()
{
int x = , f = ; char ch = getchar();
while(ch < '' || ch > ''){ if(ch == '-') f = -; ch = getchar();}
while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
return x * f;
} int tot=-,n,L[*MAXN+];
int l2[MAXN*+],l[MAXN+],r[MAXN+];
int f[MAXN+][MAXN*+];
int inv[MAXN+],p[MAXN+]; main()
{
p[]=inv[]=p[]=inv[]=;
for(int i=;i<=MAXN;i++)
{
p[i]=1LL*p[i-]*i%mod;
inv[i]=1LL*(mod-mod/i)*inv[mod%i]%mod;
}
//for(int i=2;i<=MAXN;i++) inv[i]=1LL*inv[i]*inv[i-1]%mod;
n=read();
for(int i=;i<=n;i++)
{
l[i]=l2[i*-]=read();
r[i]=l2[i<<]=read();l2[i<<]+=;
}
sort(l2+,l2+n*+);
for(int j=;j<=n*;j++)if(l2[j]!=l2[j-])
l2[++tot]=l2[j]; tot++;
for(int i=;i<tot;i++) L[i]=l2[i]-l2[i-];
for(int i=;i<=n;i++)
{
l[i]=upper_bound(l2,l2+tot,l[i])-l2;
r[i]=upper_bound(l2,l2+tot,r[i])-l2;
// cout<<l[i]<<" "<<r[i]<<endl;
}
for(int i=;i<tot;i++) f[][i]=;
for(int i=;i<=n;i++)
{
f[i][]=;
for(int j=l[i];j<=r[i];j++)
{
f[i][j]=(long long)L[j]*f[i-][j-]%mod;//cout<<f[i][j]<<endl;
int now=;long long c=L[j]-;
for(int k=i-;k;--k)
if(l[k]<=j&&j<=r[k])
{
now++;
c=c*(long long)(L[j]+now-)%mod*inv[now]%mod;
if(!c)break;
f[i][j]=(f[i][j]+(long long)f[k-][j-]*c)%mod;
}
}
for(int j=;j<tot;j++)
f[i][j]=((long long)f[i][j]+f[i-][j]+f[i][j-]-f[i-][j-]+mod)%mod;
// for(int j=1;j<tot;j++)
// cout<<i<<" "<<j<<" "<<f[i][j]<<endl;
}
cout<<(long long)(f[n][tot-]-+mod)%mod;
return ;
}

B.给定一棵n个非叶节点,m个叶节点的树,有边权,定义修改边权的费用为前后边权的差的绝对值,你要让所有叶节点到根节点的距离相同,但又不能把边权改成负数,求最小费用。

n,m<=300000

题解:我们用f[i][j]表示第i个点,子树中的叶节点到它的距离都是j的最小费用,那么f[i][0]=∑Wjk   (jk都在子树i中)。

很显然,f函数是一个下凸的函数,并且存在一些拐点,拐点前后斜率变化是1,但是拐点可以重在某一个点上。只有一个叶节点时,拐点有两个,且都为于0,凸壳形状像一个绝对值函数。

所以我们只要知道所有拐点,就可以知道这个函数啦。

我们考虑向一个子树添加边时候的影响,由于w可以无限增大,在一定大小后只修改这一条边一定最优,斜率肯定都是1,所以对于斜率大于1的部分我们都可以舍去,即弹掉所有原来斜率大等0的拐点。

这样一次合并我们实际上只把它向右平移了一下。需要删除和合并操作,所以写一个可并堆就好啦。

复杂度(n+m)log(n+m)

#include<iostream>
#include<cstdio>
#define MN 600000
#define ll long long
using namespace std;
inline int read()
{
int x = , f = ; char ch = getchar();
while(ch < '' || ch > ''){ if(ch == '-') f = -; ch = getchar();}
while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
return x * f;
} int n,m,fa[MN+],in[MN+];
ll w[MN+],ans=; struct Heap{
Heap *l,*r;
ll p;int d;
Heap(ll _p):p(_p),l(),r(),d(){};
inline friend int dis(Heap*x){return x?x->d:;}
friend Heap* Merge(Heap*x,Heap*y)
{
if(!x) return y;if(!y) return x;
if(x->p<y->p) swap(x,y);
x->r=Merge(x->r,y);
if(dis(x->r)>dis(x->l)) swap(x->l,x->r);
x->d=dis(x->r)+; return x;
}
}*s[MN+],*a,*b; int main()
{
n=read();m=read();n+=m;
for(int i=;i<=n;i++)
{++in[fa[i]=read()];ans+=(w[i]=read());}
for(int i=n;i>;i--)
{
if(!s[i]) s[i]=Merge(new Heap(),new Heap());
for(int j=;j<in[i];j++)
s[i]=Merge(s[i]->l,s[i]->r);
a=new Heap(s[i]->p+w[i]);s[i]=Merge(s[i]->l,s[i]->r);
b=new Heap(s[i]->p+w[i]);s[i]=Merge(s[i]->l,s[i]->r);
s[fa[i]]=Merge(s[fa[i]],Merge(s[i],Merge(a,b)));
}
int top=;
while(s[])w[++top]=s[]->p,s[]=Merge(s[]->l,s[]->r);w[top+]=;
for(int i=top;m;m--,i--) ans-=(w[i]-w[i+])*m;
printf("%lld\n",ans);
return ;
}

C.Gap

给定一个长度为n的严格递增数列,你每次可以询问一个数字区间的最大值,最小值,求最大差分。n<=100000

题解:对于subtask1,询问次数不超过(n+1)/2,我们枚举左右节点查,然后缩短这个区间就好啦。

对于subtask2,询问的区间含有k个数时费用是k+1,要让费用不超过3n。我们先求最大值x和最小值y,显然答案不会低于(y-x)/(n-1),所以我们把数字分块,每块内不存在答案,都询问一次就行了。

#include "gap.h"
#include<algorithm>
#include<iostream>
using namespace std;
#define ll long long
#define INF 1000000000000000000LL
ll s[];
ll ans=;
int cnt=; ll solve(int x)
{
ll l,r;
MinMax(,INF,s+,s+x);cnt=;int i=,j=x-;
for(l=s[]+,r=s[x]-;i<=j;l=s[i++]+,r=s[j--]-)
{
MinMax(l,r,s+i,s+j);
}
for(int i=;i<=x;i++)
ans=max(ans,s[i]-s[i-]);
return ans;
} ll findGap(int T, int N)
{
if(T==) return solve(N);
if(N==) return ;
MinMax(,INF,s+,s+);cnt=;
ll p=(s[]-s[]-)/(N-)+;
for(ll i=s[]+;i<=s[]-;i+=p)
{
MinMax(i,min(i+p-,s[]-),s+cnt+,s+cnt+);
if(s[cnt+]>)cnt+=;
}
sort(s+,s+cnt+);
for(int i=;i<=cnt;i++)
ans=max(ans,s[i]-s[i-]);
return ans;
}

[APIO2016]的更多相关文章

  1. BZOJ 4584 luogu P3643: [Apio2016]赛艇

    4584: [Apio2016]赛艇 Time Limit: 70 Sec  Memory Limit: 256 MB[Submit][Status][Discuss] Description 在首尔 ...

  2. [洛谷P3643] [APIO2016]划艇

    洛谷题目链接:[APIO2016]划艇 题目描述 在首尔城中,汉江横贯东西.在汉江的北岸,从西向东星星点点地分布着 \(N\) 个划艇学校,编号依次为 \(1\) 到 \(N\).每个学校都拥有若干艘 ...

  3. 【APIO2016】Fireworks[DP 可并堆维护凸包优化]

    4585: [Apio2016]烟火表演 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 100  Solved: 66[Submit][Status] ...

  4. 【BZOJ4584】[Apio2016]赛艇 DP

    [BZOJ4584][Apio2016]赛艇 Description 在首尔城中,汉江横贯东西.在汉江的北岸,从西向东星星点点地分布着个划艇学校,编号依次为到.每个学校都拥有若干艘划艇.同一所学校的所 ...

  5. UOJ #205/BZOJ 4585 【APIO2016】Fireworks 可并堆+凸包优化Dp

    4585: [Apio2016]烟火表演 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 115  Solved: 79[Submit][Status] ...

  6. Loj #2568. 「APIO2016」烟花表演

    Loj #2568. 「APIO2016」烟花表演 题目描述 烟花表演是最引人注目的节日活动之一.在表演中,所有的烟花必须同时爆炸.为了确保安全,烟花被安置在远离开关的位置上,通过一些导火索与开关相连 ...

  7. 「APIO2016」烟花表演

    「APIO2016」烟花表演 解题思路 又是一道 solpe trick 题,观察出图像变化后不找一些性质还是挺难做的. 首先令 \(dp[u][i]\) 为节点 \(u\) 极其子树所有叶子到 \( ...

  8. 写在APIO2016之前

    时间过得真快.仿佛前天的我还在为联赛的MLE悲伤,昨天的我还在为省选看错题而崩溃,今天就到了APIO的前夜了.虽然明天不是正赛,但我的学弟们都是明天离开.也就是说,我只能为在遥远帝都的他们默默地祈祷了 ...

  9. P3643 [APIO2016]划艇

    P3643 [APIO2016]划艇 题意 一个合法序列可表示为一个长度为 \(n\) 的序列,其中第 \(i\) 个数可以为 0 或 \([l_i,r_i]\) 中一个整数,且满足所有不为零的数组成 ...

  10. CTSC2016&&APIO2016滚粗记&&酱油记&&游记<del>(持续更新)</del>

    挖一波坑 #include <cstdio> using namespace std; int main(){ puts("转载请注明出处:http://www.cnblogs. ...

随机推荐

  1. Python 迭代器之列表解析

     [TOC] 尽管while和for循环能够执行大多数重复性任务, 但是由于序列的迭代需求如此常见和广泛, 以至于Python提供了额外的工具以使其更简单和高效. 迭代器在Python中是以C语言的 ...

  2. JAVA_SE基础——28.封装

    黑马程序员blog... 面向对象三大特征:1. 封装2. 继承3  多态. 今天我们先学习第一大特征,封装. 封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式. 好处:     1. 将变 ...

  3. 20170222==(MODBUS读取多个寄存器)

    MODBUS读取多个寄存器(功能码04) 为了简单我这里只用4个寄存器,当让你也可以用125个寄存器,但是最多也只能用125个寄存器的.每个寄存器有上面的表知道为一个字的大小即2个字节或者叫16比特位 ...

  4. vmware 12 安装 mac os 10.12正式版

    1.首先下载安装vmware 12 pro ,将VT打开(虚拟功能,以前安装过虚拟机点的同学可忽略). 2.下载mac ox 10.12正式版镜像文件(cdr后缀). 3.下载Unlocker208( ...

  5. C# 使用 ffmpeg 进行音频转码

    先放一下 ffmpeg 的官方文档以及下载地址: 官方文档:http://ffmpeg.org/ffmpeg.html 下载地址:http://ffmpeg.org/download.html 用 f ...

  6. 第三章Hibernate关联映射

    第三章Hibernate关联映射 一.关联关系 类与类之间最普通的关系就是关联关系,而且关联是有方向的. 以部门和员工为列,一个部门下有多个员工,而一个员工只能属于一个部门,从员工到部门就是多对一关联 ...

  7. [UWP]针对UWP程序多语言支持的总结,含RTL

    UWP 对 Globalization and localization 的支持非常好,可以非常容易地实现应用程序本地化. 所谓本地化,表现最为直观的就是UI上文字和布局方式了,针对文字,提供不同的语 ...

  8. SpringMvc(4-1)Spring MVC 中的 forward 和 redirect

    Spring MVC 中,我们在返回逻辑视图时,框架会通过 viewResolver 来解析得到具体的 View,然后向浏览器渲染.通过配置,我们配置某个 ViewResolver 如下: <b ...

  9. Python学习之条件判断和循环

    #coding= utf-8 # 条件判断和循环 # 如果if语句判断是True,就把缩进的两行print语句执行了,否则,什么也不做 age1 = 20 if age1 >= 18: prin ...

  10. java中的引用类型的对象存放在哪里

    根据上下文来确定.比如void func(){    Object obj = new Object();//这个obj在函数的栈里.}class Test{   private Object obj ...