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. 【转】Python 访问 HDFS

    1.前言 hdfs , Hadoop Distributed File System.Hadoop的分布式文件系统,安全行和扩展性没得说. 访问HDFS的方式有以下几种: 命令行方式:FS Shell ...

  2. ZOJ Monthly, January 2019-Little Sub and Pascal's Triangle

    这个题的话,它每行奇数的个数等于该行行号,如果是0开始的,就该数的二进制中的1的个数,设为k,以它作为次数,2k就是了. #include <stdio.h> int main() { i ...

  3. Re:从零开始的Linux之路(基础篇)

    基于 Red Hat Enterprise Linux 7.5 或者 CentOS 7.4 Linux的命令一定遵循以下格式:command指令  [-options]选项  parameter1参数 ...

  4. CentOS7.5下开发systemctl管理的自定义Nginx启动服务程序

    一.systemctl知识简介 从CentOS7 Linux开始,系统里的网络服务启动已经从传统的service改成了systemctl(一个systemd工具,主要负责控制systemd系统和服务管 ...

  5. python--类的约束, 异常处理, MD5, 日志处理

    一 . 类的约束 1. 写一个父类,父类中的某个方法要抛出一个异常 NotImplementedError class Base: # 对子类进行了约束. 必须重写该方法 # 以后上班了. 拿到公司代 ...

  6. (原)iOS 用recursiveDescription打印View

    今天要做一个搜索功能,用到UISearchBar 无奈背景太丑,就自定义了一个,首先用View私有方法打印一下searchBar的层次, 具体修改代码如下 for (UIView *view in _ ...

  7. 多线程并发情况下 重复insert问题

    代码逻辑: if(数据不存在){ insert(); } 线程启动后,发现数据库表中有相同的记录 解决方案 synchronized同步代码块即加同步锁,synchronized同步代码块的功能: 当 ...

  8. ZZULIoj 1907 小火山的宝藏收益

    Description      进去宝藏后, 小火山发现宝藏有N个房间,且这n个房间通过N-1道门联通.   每一个房间都有一个价值为Ai的宝藏, 但是每一个房间也都存在一个机关.如果小火山取走了这 ...

  9. WIN10配置MAVEN

    添加新的系统环境变量M2_HOME, 并设置其值为你安装的目录MAVEN_HOME=D:\Softwares\apache-maven-3.2.2. 更新系统PATH 变量, 添加;%M2_HOME% ...

  10. Experiments done

    喷重金属 换重金属溶液 荧光光合 备注 ASD 备注 高光谱 备注 泡EDTA 备注 电镜 备注 2018.12.19(day1) 2018.12.19(day1) 2018.12.18晚(day0) ...