T1 水题(water)

Time Limit:1000ms   Memory Limit:128MB

题目描述

LYK出了道水题。

这个水题是这样的:有两副牌,每副牌都有n张。

对于第一副牌的每张牌长和宽分别是xi和yi。对于第二副牌的每张牌长和宽分别是aj和bj。第一副牌的第i张牌能覆盖第二副牌的第j张牌当且仅当xi>=aj并且yi>=bj。(注意牌不能翻转)当然一张牌只能去覆盖最多一张牌,而不能覆盖好多张。

LYK想让两副牌的各n张一一对应叠起来。它想知道第二副牌最多有几张能被第一副牌所覆盖。

输入格式(water.in)

第一行一个数n。

接下来n行,每行两个数xi,yi。

接下来n行,每行两个数aj,bj。

输出格式(water.out)

输出一个数表示答案。

输入样例

3

2 3

5 7

6 8

4 1

2 5

3 4

输出样例

2

数据范围

对于50%的数据n<=10。

对于80%的数据n<=1000。

对于100%的数据1<=n<=100000,1<=xi,yi,aj,bj<=10^9。

 #include <algorithm>
#include <cstdio> inline void read(int &x)
{
x=; register char ch=getchar();
for(; ch>''||ch<''; ) ch=getchar();
for(; ch>=''&&ch<=''; ch=getchar()) x=x*+ch-'';
}
const int N();
int n,ans;
struct Node {
int x,y;
bool operator < (const Node&z)const
{
if(x==z.x) return y<z.y;
return x<z.x;
}
}a[N],b[N];
const int M();
int vis[M][M],sumvis;
int link[M][M],mat[M]; bool find(int u)
{
for(int v=; v<=n; ++v)
if(link[u][v]&&vis[u][v]!=sumvis)
{
vis[u][v]=sumvis;
if(!mat[v]||find(mat[v]))
{
mat[v]=u;
return ;
}
}
return ;
} inline void violence()
{
for(int i=; i<=n; ++i)
for(int j=; j<=n; ++j)
link[i][j]=(a[i].x>=b[j].x&&a[i].y>=b[j].y);
for(int i=; i<=n; ++i)
{
sumvis++;
if(find(i)) ans++;
}
printf("%d\n",ans);
} int Presist()
{
// freopen("1.txt","r",stdin);
freopen("water.in","r",stdin);
freopen("water.out","w",stdout);
read(n);
for(int i=; i<=n; ++i)
read(a[i].x),read(a[i].y);
for(int i=; i<=n; ++i)
read(b[i].x),read(b[i].y);
if(n<=) violence();
return ;
} int Aptal=Presist();
int main(int argc,char**argv){;}

匈牙利,60分

因为可能存在 xi,yi=1,,,xj==1,yj,的情况,这种情况下,无法确定怎样覆盖更优,

所以可以以xi从小到大排序,在满足xi的情况下,将B组的y放到某数据结构中,再找满足A组的y的最大的y

需要有插入,删除不超过y的最大数的数据结构,数组80,muliset/平衡树/权值线段树

 #include <algorithm>
#include <cstdio>
#include <set> inline void read(int &x)
{
x=; register char ch=getchar();
for(; ch>''||ch<''; ) ch=getchar();
for(; ch>=''&&ch<=''; ch=getchar()) x=x*+ch-'';
}
const int N(); std:: multiset<int>set_; struct Card {
int x,y;
bool operator < (const Card&c)const
{
return x<c.x;
}
}a[N],b[N]; int Presist()
{
freopen("water.in","r",stdin);
freopen("water.out","w",stdout);
int n,ans=; read(n);
for(int i=; i<=n; ++i)
read(a[i].x),read(a[i].y);
for(int i=; i<=n; ++i)
read(b[i].x),read(b[i].y);
std:: sort(a+,a+n+);
std:: sort(b+,b+n+);
for(int i=,j=; i<=n; ++i)
{
for(; a[i].x>=b[j].x&&j<=n; )
set_.insert(b[j].y),++j;
if(set_.empty()) continue;
std:: multiset<int>:: iterator it=set_.upper_bound(a[i].y);
if(it==set_.begin()) continue;
else ans++,set_.erase(--it);
}
printf("%d\n",ans);
return ;
} int Aptal=Presist();
int main(int argc,char**argv){;}

AC

T2 梦境(dream)

Time Limit:1000ms   Memory Limit:128MB

题目描述

LYK做了一个梦。

这个梦是这样的,LYK是一个财主,有一个仆人在为LYK打工。

不幸的是,又到了月末,到了给仆人发工资的时间。但这个仆人很奇怪,它可能想要至少x块钱,并且当LYK凑不出恰好x块钱时,它不会找零钱给LYK。

LYK知道这个x一定是1~n之间的正整数。当然抠门的LYK只想付给它的仆人恰好x块钱。但LYK只有若干的金币,每个金币都价值一定数量的钱(注意任意两枚金币所代表的钱一定是不同的,且这个钱的个数一定是正整数)。LYK想带最少的金币,使得对于任意x,都能恰好拼出这么多钱。并且LYK想知道有多少携带金币的方案总数。

具体可以看样例。

输入格式(dream.in)

第一行一个数n,如题意所示。

输出格式(dream.out)

输出两个数,第一个数表示LYK至少携带的金币个数,第二数表示方案总数。

输入样例

6

输出样例

3 2

样例解释

LYK需要至少带3枚金币,有两种方案,分别是{1,2,3},{1,2,4}来恰好得到任意的1~n之间的x。

输入样例2

10

输出样例2

4 8

数据范围

对于30%的数据n<=10。

对于60%的数据n<=100。

对于100%的数据n<=1000。

 #include <algorithm>
#include <cstdio> #define min(a,b) (a<b?a:b) inline void read(int &x)
{
x=; register char ch=getchar();
for(; ch>''||ch<''; ) ch=getchar();
for(; ch>=''&&ch<=''; ch=getchar()) x=x*+ch-'';
}
const int N();
int n,ans,count;
bool vis[N];
int a[N]; void DFS(int num,int cnt,int sum)
{
if(sum>=n) { ans++; return ; }
if(cnt>count) { return ; }
for(int i=num+; i<=min(a[cnt+],sum+); ++i)
{
if(vis[i]) continue; vis[i]=;
DFS(i,cnt+,sum+i); vis[i]=;
}
} int Presist()
{
// freopen("1.txt","r",stdin);
freopen("dream.in","r",stdin);
freopen("dream.out","w",stdout);
read(n);
for(int sum=; sum<n; ++sum)
a[++count]=sum+,sum<<=;
DFS(,,);
printf("%d %d\n",count,ans);
return ;
} int Aptal=Presist();
int main(int argc,char**argv){;}

爆搜30

方案总数:dp,搜索

2^0+2^1+...+2^k = O(n)  k=log(n)

dfs(Max,Sum,S) // Max金币最大值,Sum所有金币的和,S金币的数量

dp[i][j][k] 当前有i个金币,金币和是j,最大的金币k。

if (dp[i][j][k]) 枚举下一枚金币是啥。

 #include <cstdio>

 #define min(a,b) (a<b?a:b)

 inline void read(int &x)
{
x=; register char ch=getchar();
for(; ch>''||ch<''; ) ch=getchar();
for(; ch>=''&&ch<=''; ch=getchar()) x=x*+ch-'';
}
int n,cnt,ans,f[][][]; int Presist()
{
freopen("dream.in","r",stdin);
freopen("dream.out","w",stdout); read(n);
for(; (<<cnt)<=n; ) cnt++;
f[][][]=;
for(int i=; i<cnt; ++i)
for(int j=; j<=n; ++j)
for(int k=; k<=n; ++k)
{
if(!f[i][j][k]) continue;
for(int p=k+; p<=j+; ++p)
f[i+][min(j+p,n)][p]+=f[i][j][k];
}
for(int i=; i<=n; ++i) ans+=f[cnt][n][i];
printf("%d %d\n",cnt,ans);
return ;
} int Aptal=Presist();
int main(int argc,char**argv){;}

AC

T3 动态规划(dp)

Time Limit:1000ms   Memory Limit:128MB

题目描述

LYK在学习dp,有一天它看到了一道关于dp的题目。

这个题目是这个样子的:一开始有n个数,一段区间的价值为这段区间相同的数的对数。我们想把这n个数切成恰好k段区间。之后这n个数的价值为这k段区间的价值和。我们想让最终这n个数的价值和尽可能少。

例如6个数1,1,2,2,3,3要切成3段,一个好方法是切成[1],[1,2],[2,3,3],这样只有第三个区间有1的价值。因此这6个数的价值为1。

LYK并不会做,丢给了你。

输入格式(dp.in)

第一行两个数n,k。

接下来一行n个数ai表示这n个数。

输出格式(dp.out)

一个数表示答案。

输入样例

10 2

1 2 1 2 1 2 1 2 1 2

输出样例

8

数据范围

对于30%的数据n<=10。

对于60%的数据n<=1000。

对于100%的数据1<=n<=100000,1<=k<=min(n,20),1<=ai<=n。

其中有30%的数据满足ai完全相同均匀分布在所有数据中。

dp[i][j] 1~i 切了j刀,的最优解

dp[i][j]=min{dp[k][j-1]+sum(k+1,i)}

这个k是从大到小进行枚举,每次枚举时更新这个sum 20*n^2  60分

 #include <cstring>
#include <cstdio> #define min(a,b) (a<b?a:b)
#define LL long long inline void read(int &x)
{
x=; register char ch=getchar();
for(; ch>''||ch<''; ) ch=getchar();
for(; ch>=''&&ch<=''; ch=getchar()) x=x*+ch-'';
}
const int N();
int a[N],cnt[N],L,R;
int sum[][];
LL f[][]; int Presist()
{
freopen("dp.in","r",stdin);
freopen("dp.out","w",stdout); int n,k; read(n),read(k);
for(int i=; i<=n; ++i) read(a[i]);
for(int i=; i<=n; ++i)
{
++cnt[a[i]];
for(int j=i+; j<=n; ++j)
sum[i][j]=sum[i][j-]+cnt[a[j]],++cnt[a[j]];
memset(cnt,,sizeof(cnt));
}
for(int i=; i<=n; ++i)
for(int j=; j<=k; ++k)
f[i][j]=0x7fffffff;
for(int i=; i<=n; ++i)
{
f[i][]=sum[][i];
for(int j=; j<=min(i,k); ++j)
for(int t=; t<i; ++t)
f[i][j]=min(f[i][j],f[t][j-]+sum[t+][i]);
}
printf("%d\n",f[n][k]);
return ;
} int Aptal=Presist();
int main(int argc,char**argv){;}

固定j,随着i的增大,k不会减少

20*n^2的简单dp -> 在固定j的情况下 随着i的增大,k不降 -> 分治求dp值

 #include <cstring>
#include <cstdio> #define LL long long inline void read(int &x)
{
x=; register char ch=getchar();
for(; ch>''||ch<''; ) ch=getchar();
for(; ch>=''&&ch<=''; ch=getchar()) x=x*+ch-'';
}
const int N();
int a[N],cnt[N],L,R;
LL f[N],g[N],sum; inline void move(int l,int r)
{
for(; L>l; ) sum+=cnt[a[--L]]++;
for(; L<l; ) sum-=--cnt[a[L++]];
for(; R>r; ) sum-=--cnt[a[R--]];
for(; R<r; ) sum+=cnt[a[++R]]++;
} void work(int u,int v,int l,int r)
{
if(l>r) return ;
int mid=l+r>>,pos;
LL minn=0x7fffffff;
for(int i=u; i<mid&&i<=v; ++i)
{
move(i+,mid);
if(sum+f[i]<minn)
minn=sum+f[i],pos=i;
}
g[mid]=minn;
work(u,pos,l,mid-);
work(pos,v,mid+,r);
} int Presist()
{
freopen("dp.in","r",stdin);
freopen("dp.out","w",stdout); int n,k; read(n),read(k);
for(int i=; i<=n; ++i) read(a[i]);
for(int i=; i<=n; ++i) f[i]=0x7fffffff;
for(; k--; )
{
memset(cnt,,sizeof(cnt));
L=,R=,sum=,work(,n-,,n);
for(int i=; i<=n; ++i) f[i]=g[i],g[i]=;
}
printf("%lld\n",f[n]);
return ;
} int Aptal=Presist();
int main(int argc,char**argv){;}

AC

2017-10-28-afternoon-清北模拟赛的更多相关文章

  1. 2017.10.1 国庆清北 D1T1 zhx的字符串题

    题目背景 2017国庆清北D1T1 题目描述 你是能看到第一题的 friends 呢. ——hja 何大爷对字符串十分有研究,于是天天出字符串题虐杀 zhx.何大爷今天为 字符串定义了新的权值计算方法 ...

  2. 2017.10.3北京清北综合强化班DAY3

    括号序列(bracket) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK有一个括号序列,但这个序列不一定合法. 一个合法的括号序列如下: ()是合法的 ...

  3. 2017.10.4北京清北综合强化班DAY4

    财富(treasure) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK有n个小伙伴.每个小伙伴有一个身高hi. 这个游戏是这样的,LYK生活的环境是以 ...

  4. 2017.10.7北京清北综合强化班DAY7

    1.计数 (count.cpp/c/pas) 时间限制:1s 内存限制:256MB [问题描述] 给出m个数a[1],a[2],…,a[m] 求1~n中有多少数不是a[1],a[2],…,a[m]的倍 ...

  5. 2017.10.6北京清北综合强化班DAY6

    题目大意:改变一个数的位置 把一个序列变成不下降序列 题解: 设置一个pre,如果破坏单调性,就把‘删除’这个.否则把pre修改为当前元素的值. 考试时这样得了90分,是因为我的做法只能过这样的数据 ...

  6. 2017.10.5北京清北综合强化班DAY5

    拼不出的数lost.in/.out/.cpp[问题描述]3 个元素的集合{5, 1,2} 的所有子集的和分别是0,1, 2, 3, 5, 6, 7, 8.发现最小的不能由该集合子集拼出的数字是4.现在 ...

  7. 2017.10.1北京清北综合强化班DAY1

    a[问题描述]你是能看到第一题的 friends 呢.——hja何大爷对字符串十分有研究,于是天天出字符串题虐杀 zhx. 何大爷今天为字符串定义了新的权值计算方法.一个字符串 由小写字母组成,字符串 ...

  8. 2017.10.4 国庆清北 D4T2 正方形

    题目描述 在一个10000*10000的二维平面上,有n颗糖果. LYK喜欢吃糖果!并且它给自己立了规定,一定要吃其中的至少C颗糖果! 事与愿违,LYK只被允许圈出一个正方形,它只能吃在正方形里面的糖 ...

  9. 2017.10.6 国庆清北 D6T2 同余方程组

    题目描述 求关于x 的同余方程组 x%a1 = b1 x%a2 = b2 x%a3 = b3 x%a4 = b4 的大于等于0 的最小整数解. 输入输出格式 输入格式: 一行8 个整数,表示a1; b ...

  10. 2017.10.6 国庆清北 D6T1 排序

    题目描述 小Z 有一个数字序列a1; a2; .... ; an,长度为n,小Z 只有一个操作:选 定p(1<p<n),然后把ap 从序列中拿出,然后再插⼊到序列中任意位置. 比如a 序列 ...

随机推荐

  1. 多线程threadvar 变量设定

    Delphi管理多线程之线程局部存储:threadvar 尽管多线程能够解决许多问题,但是同时它又给我们带来了很多的问题.其中主要的问题就是:对全局变量或句柄这样的全局资源如何访问?另外,当必须确保一 ...

  2. Spring框架 aop中的操作术语

    Joinpoint 连接点 Pointcut  切入点 Advice    通知/增强 举例: 后置通知,不抛出异常则执行此通知,抛异常则不执行 最终通知,抛不抛异常都通知 其他通知都是环绕通知的衍生 ...

  3. HTML5开发手机应用--viewport的作用--20150216

    在用HTML5开发手机应用或手机网页时,<head>部分总会有如下一段代码,这段代码到底什么意思呢.在网上,大家会得到很多答案.我从网上搜集了部分介绍,整理一下,以留备用. <met ...

  4. 洛谷 P2921 在农场万圣节

    https://www.luogu.org/problemnew/show/P2921 开始感觉这题30行代码就可以搞定,还是太菜啦,还是乖乖地写了tarjan. 对图进行缩点,那么这个强联通分量中的 ...

  5. hihoCoder-1109-堆优化的Prim

    优先队列是由堆组成的,所以当我们使用优先队列对Prim进行优化时,就把这种优化叫做堆优化. 它的算法核心思想就是每次向后找边,每个pair存的都是下一个点,以及边权.我们对于已经走过的点就避开,这样就 ...

  6. windows 7虚拟机与主机不能互ping通,但是都能与网关ping通

    这里是在Windows 10的环境下使用VMware安装了一个Windows 7的虚拟机,虚拟机中是使用桥接的方式.结果发现虚拟机不能与物理机互通,但是却能与网关互通.查看虚拟机和物理机的IP发现都是 ...

  7. 【Git版本控制】git---从已有分支拉出新的分支

    参考博文:git---从已有分支拉出新分支

  8. Redis数据库(一)

    1. Redis简介 Redis是非关系型数据库(nosql),数据保存在内存中,安全性低,但读取速度快. Redis主要存储变化较快且数据不是特别重要的数据. Redis是一个key-value存储 ...

  9. 如何用DOM 元素就能画出国宝熊猫

    效果预览 在线演示 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/odKrpy 可交互视频教 ...

  10. 一次下载多个文件的解决思路-JS

    一次下载多个文件的解决思路(iframe) - Eric 真实经历 最近开发项目需要做文件下载,想想挺简单的,之前也做过,后台提供下载接口,前端使用window.location.href就行了呗.不 ...