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] ...
随机推荐
- iOS 中的正则表达式符号
最近重新看了一遍 iOS 的正则文档,简单翻译下文档中涉及到的符号 1.正则表达式元字符 符号 说明 \a 响铃, \u0007 \A 匹配输入的开始,只匹配第一行,也就是忽略多行选项 \b 不在[] ...
- OpenCV 3.2 Tracking 物体跟踪
跟踪就是在连续视频帧中定位物体,通常的跟踪算法包括以下几类: 1. Dense Optical Flow 稠密光流 2. Sparse Optical Flow 稀疏光流 最典型的如KLT算法(Kan ...
- Kafka在高并发的情况下,如何避免消息丢失和消息重复?kafka消费怎么保证数据消费一次?数据的一致性和统一性?数据的完整性?
1.kafka在高并发的情况下,如何避免消息丢失和消息重复? 消息丢失解决方案: 首先对kafka进行限速, 其次启用重试机制,重试间隔时间设置长一些,最后Kafka设置acks=all,即需要相应的 ...
- Redis系列一 Redis安装
Redis系列一 Redis安装 1.安装所使用的操作系统为Ubuntu16.04 Redis版本为3.2.9 软件一般下载存放目录为/opt,以下命令操作目录均为/opt root@ubunt ...
- android分析windowManager、window、viewGroup之间关系(一)
本文将主要介绍addview方法,在windowManager.window.viewGroup中的实现原理.首先将介绍这些类结构关系,然后分析其内在联系,介绍实现原理,最后介绍重要的一个参数wind ...
- linux-centos6①
- 「日常训练」Alternative Thinking(Codeforces Round #334 Div.2 C)
题意与分析 (CodeForces - 603A) 这题真的做的我头疼的不得了,各种构造样例去分析性质... 题意是这样的:给出01字符串.可以在这个字符串中选择一个起点和一个终点使得这个连续区间内所 ...
- Jquery获取DOM绑定事件
获取到当前正在执行的事件: $('#testDive').bind('click', function(event){alert('event: ' + event.type)}); 获取所有绑定事件 ...
- 天平 (Not so Mobile UVA - 839)
题目描述: 题目思路: 1.DFS建树 2.只有每个树的左右子树都平衡整颗树才平衡 #include <iostream> using namespace std; bool solve( ...
- HADOOP docker(十):hdfs 结构体系
1.简介2.namenode和datanode3.The File System Namespace 文件系统命名空间4.Data Replication 数据复制5.Replica Placemen ...