[APIO2016]
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]的更多相关文章
- BZOJ 4584 luogu P3643: [Apio2016]赛艇
4584: [Apio2016]赛艇 Time Limit: 70 Sec Memory Limit: 256 MB[Submit][Status][Discuss] Description 在首尔 ...
- [洛谷P3643] [APIO2016]划艇
洛谷题目链接:[APIO2016]划艇 题目描述 在首尔城中,汉江横贯东西.在汉江的北岸,从西向东星星点点地分布着 \(N\) 个划艇学校,编号依次为 \(1\) 到 \(N\).每个学校都拥有若干艘 ...
- 【APIO2016】Fireworks[DP 可并堆维护凸包优化]
4585: [Apio2016]烟火表演 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 100 Solved: 66[Submit][Status] ...
- 【BZOJ4584】[Apio2016]赛艇 DP
[BZOJ4584][Apio2016]赛艇 Description 在首尔城中,汉江横贯东西.在汉江的北岸,从西向东星星点点地分布着个划艇学校,编号依次为到.每个学校都拥有若干艘划艇.同一所学校的所 ...
- UOJ #205/BZOJ 4585 【APIO2016】Fireworks 可并堆+凸包优化Dp
4585: [Apio2016]烟火表演 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 115 Solved: 79[Submit][Status] ...
- Loj #2568. 「APIO2016」烟花表演
Loj #2568. 「APIO2016」烟花表演 题目描述 烟花表演是最引人注目的节日活动之一.在表演中,所有的烟花必须同时爆炸.为了确保安全,烟花被安置在远离开关的位置上,通过一些导火索与开关相连 ...
- 「APIO2016」烟花表演
「APIO2016」烟花表演 解题思路 又是一道 solpe trick 题,观察出图像变化后不找一些性质还是挺难做的. 首先令 \(dp[u][i]\) 为节点 \(u\) 极其子树所有叶子到 \( ...
- 写在APIO2016之前
时间过得真快.仿佛前天的我还在为联赛的MLE悲伤,昨天的我还在为省选看错题而崩溃,今天就到了APIO的前夜了.虽然明天不是正赛,但我的学弟们都是明天离开.也就是说,我只能为在遥远帝都的他们默默地祈祷了 ...
- P3643 [APIO2016]划艇
P3643 [APIO2016]划艇 题意 一个合法序列可表示为一个长度为 \(n\) 的序列,其中第 \(i\) 个数可以为 0 或 \([l_i,r_i]\) 中一个整数,且满足所有不为零的数组成 ...
- CTSC2016&&APIO2016滚粗记&&酱油记&&游记<del>(持续更新)</del>
挖一波坑 #include <cstdio> using namespace std; int main(){ puts("转载请注明出处:http://www.cnblogs. ...
随机推荐
- python 面向对象设计思想发展史
这篇主要说的是程序设计思想发展历史,分为概述和详细发展历史 一,概述 1940年以前:面向机器 最早的程序设计都是采用机器语言来编写的,直接使用二进制码来表示机器能够识别和执行的 指令和数 据.简单来 ...
- nyoj 复杂度
复杂度 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 for(i=1;i<=n;i++) for(j=i+1;j<=n;j++) for(k=j+1;k ...
- JAVA_SE基础——17.方法的重载
方法重载: 方法重载就是方法名称重复,加载参数不同. 具体规范: 一.方法名一定要相同. 二.方法的参数表必须不同,包括参数的类型或个数,以此区分不同的方法体. 1.如果参数个数不同,就不管它的参数类 ...
- PC或者手机弹出窗效果
http://layer.layui.com/ 这个网站提供弹窗,是在jq封装的,弹窗之后,背景页面还可以滑动. 这个里面的js可能也会包含css,这个css不能移动位置,否则会报错,还有谷歌浏览器在 ...
- php框架中的phalcon框架的安装,及初步认识,从表单提交简单的数据到数据库中
php框架中的phalcon框架的安装,及初步认识,从表单提交简单的数据到数据库中 1.phalcon框架的安装: phalcon框架在windows本地安装可以利用wamp软件,安装之后可以查看对应 ...
- salesforce零基础学习(八十七)Apex 中Picklist类型通过Control 字段值获取Dependent List 值
注:本篇解决方案内容实现转自:http://mysalesforceescapade.blogspot.com/2015/03/getting-dependent-picklist-values-fr ...
- redis命令详解
redis中添加key value元素:set key value; 获取元素:get key ; redis中添加集合:lpush key value1 value2 value ...
- Scala入门(1)Linux下Scala(2.12.1)安装
Scala入门(1)Linux下Scala(2.12.1)安装 一.文件准备 1.1 文件名称 scala-2.12.1.tgz 1.2 下载地址 http://www.scala-lang.org/ ...
- python入门(2)python的安装
python入门(2)python的安装 Python是跨平台的,可以运行在Windows.Mac和各种Linux/Unix系统上. 2.x还是3.x Python有两个版本,一个是2.x版,一个是3 ...
- ibatis的优缺点及可行性分析
1.优点 简单: 易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现. 实用: 提供了数据映射功能,提供了对底层数据访问的封装(例如ado.net),提供了DAO框架,可以使我 ...