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. TOTP算法 基于时间的一次性密码

    /** Copyright (c) 2011 IETF Trust and the persons identified as authors of the code. All rights rese ...

  2. HAOI 2012 高速公路

    https://www.luogu.org/problem/show?pid=2221 题目描述 Y901高速公路是一条重要的交通纽带,政府部门建设初期的投入以及使用期间的养护费用都不低,因此政府在这 ...

  3. vue初尝试--新建项目

    这是一篇技术贴--如何新建一个基于vue的项目 1.下载对应版本的nodejs安装,下载的nodejs都集成了npm,所以nodejs安装完成之后npm也对应安装完成了. 安装完成之后可以在cmd命令 ...

  4. EasyUI中Tabs添加远程数据的方法。

    tabs加载远程数据: $(function () { $("#btnquery").click(function () { if (!$("#tcontent" ...

  5. SecureCRT 7.3注册机激活

    SecureCRT是一款很好用的远程登陆管理工具 工具和注册机下载链接:http://pan.baidu.com/s/1jImWiMU 密码:0yox 以管理管运行keygen.exe(一定要以管理员 ...

  6. SpringBoot14 SpringBoot整合mybatis

    1 版本说明 springboot:2.0 jdk:1.8 2 创建springBoot项目 创建项目时勾选必要web,MySQL,mybatis相关依赖 创建完成后再pom文件中添加自动部署.lom ...

  7. VMware网络配置

    NAT模式 首先保证虚拟机网卡和主机对接,虚拟机网络连接要和主机在同一网段 1. 控制面板\网络和 Internet\网络连接中配置VMnet8 2. 编辑虚拟机网络配置 此处子网ip需要和Vnet8 ...

  8. 微信接口(一)创建菜单&自动回复

    刚划拉完微信.做一个笔记这里的数据是写死的,还有一份是通过查询数据库进行自动回复,自定义菜单设置的.不过因为使用到数据库,最好在网站后台吧微信平台开发集成进去.所以代码较多就先不放了.有问题的地方请留 ...

  9. 云+社区技术沙龙:Kafka meetup 深圳站报名开启

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 如果说 2018 年是技术大爆炸年,那么 Apache Kafka 绝对是其中闪亮的新星. 自Kafka 从首发之日起,已经走过了快八个年头 ...

  10. SSM登陆注册

    package com.coingod.controller; import java.io.IOException;import java.io.PrintWriter;import java.ut ...