US Open 2016 Contest
比较弱,只写了金组和银组,铂金组的第一题。
【262144】
http://www.usaco.org/index.php?page=viewproblem2&cpid=648
给一个序列,相邻两个数组相同的可以合并变成数值大一的数,问最大能得到的数。n<262144,val<=40
是金组某道题的升级版。
因为val<40,实际上最大可以取到的不超过60.所以从1-60,看看从i开始是否能合并到当前数值。可以的话记录合并到哪一位。
初始化f[i][val[i]]=i+1,状态转移f[i][j]=f[f[i][j-1][j-1]。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<algorithm>
#include<stack>
#include<cmath>
#include<vector>
#include<map>
#define maxn 300000
using namespace std; int f[][maxn],num[maxn],ans,n; void input() {freopen("262144.in","r",stdin);freopen("262144.out","w",stdout);}
void output() {fclose(stdin);fclose(stdout);}
void work()
{
int i,k;
memset(f,,sizeof(f));
for (k=;k<=;k++) {
for (i=;i<=n;i++) {
if (num[i]==k) f[k][i]=i+;
else {
if (!k || !f[k-][i] || !f[k-][f[k-][i]]) f[k][i]=;
else f[k][i]=f[k-][f[k-][i]];
}
if (f[k][i]) ans=k;
}
f[k][n+]=;
}
return;
} int main()
{
input();
scanf("%d\n",&n);
int i;
for (i=;i<=n;i++) scanf("%d",&num[i]);
work();
printf("%d\n",ans);
output();
return ;
}
262144
AU
【Splitting the Field】
http://www.usaco.org/index.php?page=viewproblem2&cpid=645
在平面内给一些点,然后用两个矩形把所有的点围起来,矩形不能有交集和重边,问最小面积。N≤50,000
首先,两个矩形必定会在最左最右最上最下。进一步可以发现,答案一定在左右分割或者上下分割两种情况里面。
然后就排好序,扫一边求以这个点为分界划出的两个区域的面积。
两个答案取最大值。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<algorithm>
#include<stack>
#include<cmath>
#include<vector>
#include<map>
#define LL long long
#define maxn 100000
using namespace std; struct node{LL x,y;} point[maxn];
LL nmax[maxn],nmin[maxn];
int n; int cmp1(node p1,node p2){return p1.y<p2.y;}
int cmp2(node p1,node p2){return p1.x<p2.x;} void input() {freopen("1.in","r",stdin);freopen("1.out","w",stdout);}
void output() {fclose(stdin);fclose(stdout);}
int main()
{
input();
scanf("%d",&n);
int i;
for (i=;i<n;i++) scanf("%lld %lld",&point[i].x,&point[i].y);
LL ans=((LL)()<<),now1,now2,now,big1,big2;
//x
// printf("\n");
sort(point,point+n,cmp1);
big1=point[n-].y-point[].y;
nmax[n-]=point[n-].x;
nmin[n-]=point[n-].x;
for (i=n-;i>=;i--) {
nmax[i]=max(point[i].x,nmax[i+]);
nmin[i]=min(point[i].x,nmin[i+]);
}
// for (i=0;i<n;i++) printf("%lld %lld %lld %lld\n",point[i].x,point[i].y,nmin[i],nmax[i]);
now1=point[].x;
now2=point[].x;
for (i=;i<n-;i++) {
now1=max(point[i].x,now1);
now2=min(point[i].x,now2);
if (point[i+].y!=point[i].y) {
now=(point[i].y-point[].y)*(now1-now2)
+(point[n-].y-point[i+].y)*(nmax[i+]-nmin[i+]);
if (now<ans) ans=now;
}
}
// printf("%lld %d\n",ans,ans1);
//y
// printf("\n");
sort(point,point+n,cmp2);
big2=point[n-].x-point[].x;
nmax[n-]=point[n-].y;
nmin[n-]=point[n-].y;
for (i=n-;i>=;i--) {
nmax[i]=max(point[i].y,nmax[i+]);
nmin[i]=min(point[i].y,nmin[i+]);
}
// for (i=0;i<n;i++) printf("%lld %lld %lld %lld\n",point[i].x,point[i].y,nmin[i],nmax[i]);
now1=point[].y;
now2=point[].y;
for (i=;i<n-;i++) {
now1=max(point[i].y,now1);
now2=min(point[i].y,now2);
if (point[i+].x!=point[i].x) {
now=(point[i].x-point[].x)*(now1-now2)
+(point[n-].x-point[i+].x)*(nmax[i+]-nmin[i+]);
if (now<ans) ans=now;
}
} // printf("%lld %d\n",ans,ans1);
printf("%lld\n",big1*big2-ans);
output();
return ;
}
split
【Closing the Farm】
http://www.usaco.org/index.php?page=viewproblem2&cpid=646
给一个图,每次去掉一个点,问每次去掉后余下的图是否联通。
倒过来,变成每次加一个点看是否图联通。并查集做就可以。
(并查集加了启发式合并然并卵)
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<algorithm>
#include<stack>
#include<cmath>
#include<vector>
#include<map>
#define maxn 201000
#define maxm 401000
using namespace std; int to[maxm],next[maxm],first[maxn],ans[maxn],fa[maxn],rank[maxn],chose[maxn],num[maxn],n,m,total=; void input() {freopen("closing.in","r",stdin);freopen("closing.out","w",stdout);}
void output() {fclose(stdin);fclose(stdout);}
void addedge(int j,int k)
{
next[++total]=first[j];
to[first[j]=total]=k;
}
int find(int x)
{
if (fa[x]==x) return x;
return fa[x]=find(fa[x]);
} int main()
{
input();
int i,j,k;
scanf("%d %d",&n,&m);
memset(first,,sizeof(first));
for (i=;i<=m;i++) {
scanf("%d %d",&j,&k);
addedge(j,k);
addedge(k,j);
}
for (i=;i<=n;i++) scanf("%d",&num[i]);
int now=;
for (i=;i<=n;i++) fa[i]=i;
memset(chose,,sizeof(chose));
memset(ans,,sizeof(ans));
memset(rank,,sizeof(rank));
for (i=n;i;i--) {
++now;
int x=num[i];
chose[x]=;
rank[x]=;
for (j=first[x];j;j=next[j]) {
int too=to[j];
if (chose[too]) {
int fy=find(too);
int fx=find(x);
if (fy!=fx) {
--now;
if (rank[fx]>rank[fy]) fa[fy]=fx;
else {
fa[fx]=fy;
if (rank[fx]==rank[fy]) rank[fy]++;
}
}
}
}
if (now==) ans[i]=;
}
for (i=;i<=n;i++)
printf(ans[i]?"YES\n":"NO\n");
output();
return ;
}
closing
【248】
262144的弱化版。n^3dp就可以了。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<algorithm>
#include<stack>
#include<cmath>
#include<vector>
#include<map>
#define maxn 300
using namespace std; int f1[maxn][maxn],f2[maxn][maxn],f3[maxn][maxn],num[maxn],ans=,n; void input() {freopen("1.in","r",stdin);freopen("1.out","w",stdout);}
void output() {fclose(stdin);fclose(stdout);}
void dfs(int ll,int rr)
{
if (f1[ll][rr]!=-) return;
if (ll==rr) {
f1[ll][rr]=num[ll];
f2[ll][rr]=num[ll];
f3[ll][rr]=num[ll];
ans=max(ans,f1[ll][rr]);
ans=max(ans,f2[ll][rr]);
ans=max(ans,f3[ll][rr]);
return;
}
if (ll+==rr) {
if (num[ll]==num[rr]) {
f1[ll][rr]=num[ll]+;
f2[ll][rr]=num[ll]+;
f3[ll][rr]=num[rr]+;
}
else {
f1[ll][rr]=;
f2[ll][rr]=num[ll];
f3[ll][rr]=num[rr];
}
ans=max(ans,f1[ll][rr]);
ans=max(ans,f2[ll][rr]);
ans=max(ans,f3[ll][rr]);
return;
}
f1[ll][rr]=;
for (int i=ll;i<rr;i++) {
dfs(ll,i);
dfs(i+,rr);
if (f1[ll][i]==f1[i+][rr] && f1[ll][i]) f1[ll][rr]=f1[ll][i]+;
if (f2[ll][i]>f2[ll][rr]) f2[ll][rr]=f2[ll][i];
if (f3[i+][rr]>f3[ll][rr]) f3[ll][rr]=f3[i+][rr];
if (f3[ll][i]==f2[i+][rr] && f2[i+][rr])
ans=max(ans,f2[i+][rr]+);
ans=max(ans,f1[ll][rr]);
ans=max(ans,f2[ll][rr]);
ans=max(ans,f3[ll][rr]);
}
} int main()
{
input();
scanf("%d",&n);
int i,j;
for (i=;i<=n;i++) scanf("%d",&num[i]);
for (i=;i<=n;i++)
for (j=i;j<=n;j++)
f1[i][j]=-;
dfs(,n);
// for (i=1;i<=n;i++)
// for (j=i;j<=n;j++)
// printf("%d %d:%d %d %d\n",i,j,f1[i][j],f2[i][j],f3[i][j]);
printf("%d\n",ans);
output();
return ;
}
248
ag
【Field Reduction】
给一些在平面内的点,去掉三个点,问余下的点用矩形圈起来的最小面积。
直接爆搜,每次只可能去最上最下最左最右的点。4^3。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<algorithm>
#include<stack>
#include<cmath>
#include<vector>
#include<map>
#define maxn 600000
using namespace std; struct node{int x,y,num;} point[maxn],po2[maxn];
int ans,n,numx[maxn],numy[maxn],chose[maxn],p[]; int cmp1(node x,node y){return x.x<y.x;}
int cmp2(node x,node y){return x.y<y.y;} void input() {freopen("1.in","r",stdin);freopen("1.out","w",stdout);}
void output() {fclose(stdin);fclose(stdout);}
void dfs(int x)
{
int l1=-,l2=n,r1=-,r2=n;
while (!chose[numx[++l1]]);
while (!chose[numx[--l2]]);
while (!chose[numy[++r1]]);
while (!chose[numy[--r2]]);
if (x==) {
// for (int i=0;i<3;i++) printf("%d ",p[i]);printf("\n");
// printf("%d %d %d %d %d %d %d\n",numx[l1],numx[l2],numy[r1],numy[r2],
// (po2[numx[l2]].x-po2[numx[l1]].x),
// (po2[numy[r2]].y-po2[numy[r1]].y),
// (po2[numx[l2]].x-po2[numx[l1]].x)*(po2[numy[r2]].y-po2[numy[r1]].y));
ans=min((po2[numx[l2]].x-po2[numx[l1]].x)*(po2[numy[r2]].y-po2[numy[r1]].y),ans);
return;
}
chose[numx[l1]]=;
p[x]=numx[l1];
dfs(x+);
chose[numx[l1]]=; chose[numx[l2]]=;
p[x]=numx[l2];
dfs(x+);
chose[numx[l2]]=; chose[numy[r1]]=;
p[x]=numy[r1];
dfs(x+);
chose[numy[r1]]=; chose[numy[r2]]=;
p[x]=numy[r2];
dfs(x+);
chose[numy[r2]]=;
} int main()
{
input();
scanf("%d",&n);
int i;
for (i=;i<n;i++) {
scanf("%d %d",&point[i].x,&point[i].y);
point[i].num=i;
po2[i]=point[i];
}
sort(point,point+n,cmp1);
for (i=;i<n;i++) numx[i]=point[i].num;
sort(point,point+n,cmp2);
for (i=;i<n;i++) numy[i]=point[i].num;
// for (i=0;i<n;i++) printf("%d ",numx[i]);printf("\n");
// for (i=0;i<n;i++) printf("%d ",numy[i]);printf("\n");
ans=(<<)-;
for (i=;i<n;i++) chose[i]=;
dfs();
printf("%d\n",ans);
output();
return ;
}
reduce
【Diamond Collector】
给一些数,从数中选取出两个集合,要求集合内的数差不超过给定值,问两个集合数字个数和最大?
队列就可以啦,出队为当前点和队头距离大于m。然后每次的答案为之前的最大值和当前队里面数的个数。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<algorithm>
#include<stack>
#include<cmath>
#include<vector>
#include<map>
#define LL long long
#define maxn 55000
using namespace std; int f[maxn],n,ans,num[maxn],m; void input() {freopen("1.in","r",stdin);freopen("1.out","w",stdout);}
void output() {fclose(stdin);fclose(stdout);}
int main()
{
input();
scanf("%d %d",&n,&m);
int i;
for (i=;i<n;i++) scanf("%d",&num[i]);
sort(num,num+n);
int l=,r=-,ans=,now=;
while (++r<n) {
while (num[r]-num[l]>m) {
if (f[l]>ans) ans=f[l];
l++;
}
f[r]=r-l+;
// printf("%d %d %d %d %d\n",l,r,num[r],f[r],ans);
if (now<ans+f[r]) now=ans+f[r];
}
// for (i=0;i<n;i++) printf("%d %d %d\n",i,num[i],f[i]);
printf("%d\n",now);
output();
return ;
}
diamond
【Closing the Farm】同上
US Open 2016 Contest的更多相关文章
- CH0601 Genius ACM【倍增】【归并排序】
0601 Genius ACM 0x00「基本算法」例题 描述 给定一个整数 M,对于任意一个整数集合 S,定义“校验值”如下: 从集合 S 中取出 M 对数(即 2∗M 个数,不能重复使用集合中的数 ...
- 2016 Multi-University Training Contest 2 D. Differencia
Differencia Time Limit: 10000/10000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Tot ...
- 2016 Multi-University Training Contest 1 G. Rigid Frameworks
Rigid Frameworks Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) ...
- 2016 Multi-University Training Contest 1
8/11 2016 Multi-University Training Contest 1 官方题解 老年选手历险记 最小生成树+线性期望 A Abandoned country(BH) 题意: 1. ...
- 2016 Multi-University Training Contest 2
8/13 2016 Multi-University Training Contest 2官方题解 数学 A Acperience(CYD)题意: 给定一个向量,求他减去一个 α(>=0)乘以 ...
- 2016 Multi-University Training Contest 3
5/11 2016 Multi-University Training Contest 3官方题解 2016年多校训练第三场 老年选手历险记 暴力 A Sqrt Bo(CYD) 题意:问进行多少次开根 ...
- 2016 Multi-University Training Contest 4
6/12 2016 Multi-University Training Contest 4官方题解 KMP+DP A Another Meaning(CYD) 题意: 给一段字符,同时给定你一个单词, ...
- 2016 Multi-University Training Contest 5
6/12 2016 Multi-University Training Contest 5 期望+记忆化DP A ATM Mechine(BH) 题意: 去ATM取钱,已知存款在[0,K]范围内,每一 ...
- 2016 Multi-University Training Contest 6
5/12 2016 Multi-University Training Contest 6 官方题解 打表找规律/推公式 A A Boring Question(BH) 题意: ,意思就是在[0,n] ...
随机推荐
- sublime安装php_beautifier来格式化PHP代码
注:如果你使用sublime3,php版本是5.6以上,推荐使用这个插件phpfmt 环境 操作系统:windows7 sublime版本:2.0.2 PHP安装路径: D:\wamp\bin\php ...
- 第4章 TCP/IP通信案例:访问Internet上的Web服务器
第4章 TCP/IP通信案例:访问Internet上的Web服务器 4.2 部署代理服务器 书中为了演示访问Internet上的Web服务器的全过程,使用了squid代理服务器程序模拟了一个代理服务器 ...
- Linux中常用的关机和重新启动命令
hutdown.halt.reboot以及init,它们都可以达到关机和重新启动的目的,但是每个命令的内部工作过程是不同的,下面将逐一进行介绍. 一.shutdown shutdown命令用于安全关闭 ...
- 什么是Frozen Binary
对于Python来说,你可以将Python的字节码,PVM(也就是解析器),以及需要的相关类库,打包成一个package,这个package实际上是一个二进制可执行文件,这样,用户获取到这个packa ...
- Python—集合(在我的世界,你就是唯一)
一.概念与定义 集合类型与数学中集合的概念一致,即包含0个或多个数据项的无序组合. 元素不可重复,只能是固定数据类型元素. 集合(set)属于Python无序可变序列,使用一对大括号作为定界符,元素之 ...
- Thunder团队第六周 - Scrum会议2
Scrum会议2 小组名称:Thunder 项目名称:i阅app Scrum Master:宋雨 工作照片: 参会成员: 王航:http://www.cnblogs.com/wangh013/ 李传康 ...
- 20172330 2017-2018-1 《Java程序设计》第五周学习总结
20172330 2017-2018-1 <Java程序设计>第五周学习总结 教材学习内容总结 第五章 首先是对各种各种运算符的了解:刚开始以为相等就是=,还有其他一些符号都挺简单的,然后 ...
- 常用算法Java实现之冒泡排序
冒泡排序是所有排序算法中最基本.最简单的一种.思想就是交换排序,通过比较和交换相邻的数据来达到排序的目的. 具体流程如下: 1.对要排序的数组中的数据,依次比较相邻的两个数据的大小. 2.如果前面的数 ...
- BluetoothDevice详解
一. BluetoothDevice简介 1. 继承关系 public static Class BluetoothDevice extends Object implement Parcelable ...
- Java容器之Set接口
Set 接口: 1. Set 接口是 Collection 的子接口,Set 接口没有提供额外的方法,但实现 Set 接口的容器类中的元素是没有顺序的,且不可以重复: 2. Set 容器可以与数学中的 ...