【杂题1】USACO 2018 Open Contest-练习
https://www.xoj.red/contests/show/1231
下面会写一些题目的解析什么的,当然不会粘贴题目只是简单提一下
(部分题目简单的题目就不概括了)
其实难度应该前面比较低.
本题求出冒泡排序需要几趟。
考虑一次冒泡排序的交换,减小对应1个位子上的1个逆序对。
但是对于每一个位子所需要减小的逆序对数量是不一样的。
对于每一趟,消去每一个位子上1个逆序对
所以趟数就是每个位子上的数产生逆序对数的最大值。
最后的+1指的是即使上一次已经消除所有逆序对了,我们并不知道数组有序了,所以判断最后一遍查看是否有序。
考虑树状数组维护$O(n log_2 n)$
和善的树状数组代码如下:
# include <bits/stdc++.h>
using namespace std;
const int N=1e5+;
int a[N],tmp[N],c[N];
int n,T;
void update(int x){for (;x<=n;x+=x&-x)c[x]++;}
int query(int x){int ret=;for (;x;x-=x&-x) ret+=c[x];return ret;}
int main()
{
scanf("%d",&n); tmp[]=n;
for (int i=;i<=n;i++) scanf("%d",&a[i]),tmp[i]=a[i];
sort(tmp+,tmp+tmp[]+);
T=unique(tmp+,tmp++tmp[])-tmp-;
int ans=;
for (int i=;i<=n;i++) {
int w=lower_bound(tmp+,tmp++T,a[i])-tmp;
update(w);
ans=max(i-query(w),ans);
}
printf("%d\n",ans+);
return ;
}
问题A: 3894: Out of Sorts
考虑一个简单的贪心,每次选择当前等待奶牛数目最多的一个,占用等待奶牛数少的奶牛的位置。
如果不是这样做,对答案会有正贡献,是我们不期望的,与答案最优性矛盾,我们选择一个一定是最优的决策。
# include <bits/stdc++.h>
using namespace std;
const int N=1e5+;
int n,a[N];
int main()
{
scanf("%d",&n);
for (int i=;i<=n;i++) scanf("%d",&a[i]);
sort(a+,a++n);
int cnt=,Ans=;
for (int i=n;i>=;i--) {
if (cnt<=a[i])Ans++,cnt++;
else break;
}
printf("%d\n",Ans);
return ;
}
问题B: 3895: Lemonade Line
大概是不存在一个正解的。
考虑这样一个事情,如果正反来了一边那么每一次对于i位置上的数a[i]来说他左边位置j $\in $ [1,i-1]比a[i]严格大的数有一个被放到了i的右边
他右边的位置j$\in $ [i+1,n]比a[i]严格小的数有一个被放到了i的左边。当且仅当a[i]左边和右边不存在上述的数那么停止。
如果把一个数组变为有序显然第i个位子上放置第i大的数。
显然他们的位置一定在i位置后面。所有至少需要移动这么多次,把每一个比i大的数移动到i的右面。
显然我们冒泡1次对于每个i对应的有多少数在他左边只能减少1个这样的数,所以答案就是max{前i个数里面有多少个数字离散化后是比i大的,1}
# include <bits/stdc++.h>
using namespace std;
const int N=1e5+;
int c[N],n;
struct rec{int x,id;}a[N];
bool cmp(rec a,rec b)
{
if (a.x!=b.x) return a.x<b.x;
return a.id<b.id;
}
void update(int x){for (;x<=n;x+=x&-x) c[x]++;}
int query(int x){int ret=; for (;x;x-=x&-x) ret+=c[x]; return ret;}
int main()
{
scanf("%d",&n);
for (int i=;i<=n;i++)
scanf("%d",&a[i].x),a[i].id=i;
sort(a+,a++n,cmp);
int ans=;
for (int i=;i<=n;i++){
update(a[i].id);
ans=max(ans,i-query(i));
}
printf("%d\n",ans);
return ;
}
问题D: 3897: Out of Sorts
本题要求最大化pos满足前面若干条边连起来是一个无环图。
求最优遍历顺序,想到拓扑排序check+二分答案,然后手打堆优化STL常数。
先存输入,每一次二分答案位置pos,把前面pos个连边系统前面连到后面,然后跑拓扑,每次选择入度为0,标号最小的一个遍历
这里用到heap了,然后使用priority_queue在不开O2情况下TLE,然后就写了一个手写堆。
# include <bits/stdc++.h>
using namespace std;
const int N=1e5+,M=2e5+;
int head[N],ind[N],ans[N];
bool vis[N];
vector<int>ipt[N];
int n,m,tot;
struct rec{int pre,to;}a[M];
inline int read()
{
int X=,w=; char c=;
while(c<''||c>'') {w|=c=='-';c=getchar();}
while(c>=''&&c<='') X=(X<<)+(X<<)+(c^),c=getchar();
return w?-X:X;
}
inline void write(int x)
{
if (x>) write(x/);
putchar(''+x%);
}
void adde(int u,int v)
{
ind[v]++;
a[++tot].pre=head[u];
a[tot].to=v;
head[u]=tot;
}
struct heap{
# define lson (x<<)
# define rson ((x<<)+)
# define fath (x>>)
int Size,c[N<<];
heap(){Size=;}
void down(int x) {
while (x<Size) {
if (lson>Size) break;
int t=lson;
if (rson<=Size&&c[rson]<c[lson]) t=rson;
if (c[x]<=c[t]) break;
swap(c[x],c[t]);
x=t;
}
}
void up(int x) {
while (x) {
if (c[x]>c[fath]) break;
swap(c[x],c[fath]);
x=fath;
}
}
int top(){return c[];}
void push(int x){c[++Size]=x;up(Size);}
void pop() {swap(c[],c[Size--]);down();}
bool empty(){ return !Size;}
}q;
bool check(int Mid)
{
tot=;
memset(vis,false,sizeof(vis));
memset(head,,sizeof(head));
memset(ind,,sizeof(ind));
for (int i=;i<=Mid;i++)
for (int j=;j<ipt[i].size();j++)
adde(ipt[i][j-],ipt[i][j]);
for (int i=;i<=n;i++)
if (ind[i]==) q.push(i);
ans[]=;
while (!q.empty()) {
int u=q.top(); q.pop();
vis[u]=true;
ans[++ans[]]=u;
for (int i=head[u];i;i=a[i].pre){
int v=a[i].to;
if (ind[v]==) return false;
ind[v]--;
if (ind[v]==) q.push(v);
}
}
for (int i=;i<=n;i++)
if (!vis[i]) return false;
return true;
}
int main()
{
n=read();m=read();
for (int i=;i<=m;i++) {
int r=read();
for (int j=;j<=r;j++) {
int t=read();
ipt[i].push_back(t);
}
}
int L=,R=m,Ans=;
while (L<=R) {
int mid=(L+R)>>;
if (check(mid)) Ans=mid,L=mid+;
else R=mid-;
}
if (Ans==) {
for (int i=;i<=n;i++) write(i),putchar(' ');
putchar('\n');
return ;
}
check(Ans);
for (int i=;i<=n;i++) write(ans[i]),putchar(' ');
putchar('\n');
return ;
}
问题E: 3898: Milking Order
考虑01分数规划,即二分答案套dp检查。
设答案$x\leq \frac{\sum w_i}{\sum t_i} $移项可得$\sum t_i - x \sum w_i \geq 0$
即要求我们对于给定参数x,求一组$w_i$和$t_i$满足$\sum t_i - x \sum w_i \geq 0$
即$max\{ \sum t_i - x \sum w_i \} \geq 0$
对于第i头奶牛的贡献就变成一个确定的数了,即$t_i-xw_i$
考虑01背包。
设f[x]表示当前选择总重量为x,$\sum t_i - x \sum w_i $的最大值。
考虑从x转移出去对x+w[i]有影响,有转移方程$f[x+w[i]]=max(f[x+w[i]],f[x]+t_i-xw_i)$
然后要求总重量超过W,事实上我们并不关心到底超过W多少,只要超过就行,那么就统计在恰好的地方
即统计在f[W]处,那么f[W]就是答案。
# include <bits/stdc++.h>
# define inf (<<)
using namespace std;
const int N=1e5+;
double f[N];
int w[N],t[N];
int n,W;
bool check(double x)
{
f[]=;
for(int i=;i<=W;i++) f[i]=-inf;
for (int i=;i<=n;i++)
for (int j=W;j>=;j--)
f[min(j+w[i],W)]=max(f[min(j+w[i],W)],f[j]+t[i]-x*w[i]);
return f[W]>=0.0;
}
int main()
{
scanf("%d%d",&n,&W);
for (int i=;i<=n;i++)
scanf("%d%d",&w[i],&t[i]);
double l=,r=inf,ans;
while (r-l>=(1e-)){
double mid=(l+r)/2.0;
if (check(mid)) ans=mid,l=mid;
else r=mid;
}
ans=ans*;
printf("%d\n",(int)ans);
return ;
}
问题F: 3899: Talent Show
我们不妨宏观考虑这个排序的问题,在对于A进行子冒泡排序的时候,可以发现,比第i个元素小的元素且在i右边的元素是以1贡献/次向i移动的。
所以第i个元素和第i+1元素之间的隔板产生的区间长度就是$ (maxpos-i+1-1)=maxpos-i $,其中$ maxpos $指的是排序以后比$a_i$元素更小的,但排在$a_i$元素的右边,且距离$a_i$最远的数$a_j$的下标(位置)$j$。
对于i被计算1次当他的前面隔板不是连续的,或者 后面隔板不是连续的满足其一即可,所以若把i存在于的这个隔板不连续的区间排成有序,那么仅对于元素i它被算的次数(产生的贡献)是$max(t_{i-1},t_i)$
说明一下: 如果i前后隔板都不连续的话i被产生$max(t_{i-1},t_i)$后便不产生贡献了,如果前面或后面隔板不连续显然。
有了上面的说明,这个题目的算法呼之欲出,
1. 遍历原数组,当前位置为i,求出$ t_i $,查找最后一个比$a_i$小的数出现的位置为j,令$ t_i = j - i $
2. 求出 $ans = \sum\limits_{i=1} ^ {n} \max \{ t_{i-1}, t_i \}$ 并输出。
显然按照上面模拟是$ O(n^2) $算法。
我们可以这样做,先把$a_i$每个元素记录它的值$val$和下标$i$,排序。
那么求一个前缀$ maxpos=max{a[i].id , maxpos }$,显然遍历到i位置的时候,前面都是比$ a[i] $ 的值,然后前面最大的$ id $号码就是$ maxpos $。
那么时间复杂度就降到$ O(nlog_2n) $
# include <bits/stdc++.h>
# define int long long
using namespace std;
const int N=1e5+;
struct rec{ int val,id; }a[N];
int n,t[N];
bool cmp(rec a,rec b)
{
if (a.val!=b.val) return a.val<b.val;
else return a.id<b.id;
}
signed main()
{
scanf("%lld",&n);
for (int i=;i<=n;i++)
scanf("%lld",&a[i].val),a[i].id=i;
sort(a+,a++n,cmp);
int maxpos=;
for (int i=;i<=n;i++) {
maxpos=max(maxpos,a[i].id);
t[i]=max(1ll,maxpos-i);
}
int ans=;
for (int i=;i<=n;i++)
ans+=max(t[i],t[i-]);
cout<<ans;
return ;
}
问题G: 3900: Out of Sorts
这个题目非常有价值,我想专门开一个blog讲一讲这个题。
https://www.cnblogs.com/ljc20020730/p/10467324.html
欢迎支持!!!
【杂题1】USACO 2018 Open Contest-练习的更多相关文章
- [USACO 2018 December Contest]作业总结
t1 Convention 题目大意 每一头牛都有一个来的时间,一共有\(n\)辆车,求出等待时间最长的那头牛等待的最小时间. 解法 第一眼看到这道题还以为是\(2018noip\)普及组的t3魔鬼题 ...
- [USACO 2018 Open Contest]作业总结
t1-Out of Sorts 题目大意 将最大的数冒泡排序到最后需要多少次操作. 分析 排序后判断距离. ac代码 #include<bits/stdc++.h> #define N 1 ...
- 【二分+拓扑排序】Milking Order @USACO 2018 US Open Contest, Gold/upc_exam_6348
目录 Milking Order @USACO 2018 US Open Contest, Gold/upc_exam_6348 PROBLEM 题目描述 输入 输出 样例输入 样例输出 提示 MEA ...
- 【USACO 2019 Feburary Contest】Gold
模拟二月金组,三个半小时AK. USACO 2019 Feburary Contest, Gold T1 题意:给定一棵树,每个点有点权,每次可以进行以下操作之一: 更改一个点的点权 求某条路径上的点 ...
- [USACO 2018 Feb Gold] Tutorial
Link: USACO 2018 Feb Gold 传送门 A: $dp[i][j][k]$表示前$i$个中有$j$个0且末位为$k$的最优解 状态数$O(n^3)$ #include <bit ...
- 贪心/构造/DP 杂题选做Ⅲ
颓!颓!颓!(bushi 前传: 贪心/构造/DP 杂题选做 贪心/构造/DP 杂题选做Ⅱ 51. CF758E Broken Tree 讲个笑话,这道题是 11.3 模拟赛的 T2,模拟赛里那道题的 ...
- COCI 2018/2019 CONTEST #2 T4 Maja T5Sunčanje Solution
COCI 2018/2019 CONTEST #2 T4 T5 Solution abstract 花式暴力 #2 T5 Sunčanje 题意 按顺序给你1e5个长方形(左下角坐标&& ...
- [USACO 2018 Jan Gold] Tutorial
Link: USACO 2018 Jan Gold 传送门 A: 对于不同的$k$,发现限制就是小于$k$的边不能走 那么此时的答案就是由大于等于$k$的边形成的图中$v$所在的连通块除去$v$的大小 ...
- 正睿OI DAY3 杂题选讲
正睿OI DAY3 杂题选讲 CodeChef MSTONES n个点,可以构造7条直线使得每个点都在直线上,找到一条直线使得上面的点最多 随机化算法,check到答案的概率为\(1/49\) \(n ...
- dp杂题(根据个人进度选更)
----19.7.30 今天又开了一个新专题,dp杂题,我依旧按照之前一样,这一个专题更在一起,根据个人进度选更题目; dp就是动态规划,本人认为,动态规划的核心就是dp状态的设立以及dp转移方程的推 ...
随机推荐
- npm install报错 npm ERR! enoent ENOENT: no such file or directory
在npm之后出现如下错误: $ npm install npm WARN checkPermissions Missing write access to /Users/lucas/code/js/v ...
- C# 实现表单的自动化测试<通过程序控制一个网页>
学历代表你的过去,能力代表你的现在,学习代表你的将来 十年河东,十年河西,莫欺少年穷 学无止境,精益求精 C# 实现表单的自动化测试,这标题看着就来劲!那么,如何通过C#程序控制一个网页呢? 在此,以 ...
- Mybatis中 collection 和 association 的区别?
public class A{ private B b1; private List<B> b2;} 在映射b1属性时用association标签,(一对一的关系) 映射b2时用colle ...
- oracle如何导出和导入数据库/表
oracle如何导出和导入数据库/表 oracle如何将项目中的表导出后在导入自己的数据库中,这是一个完整的操作,对于数据库备份或在本地查看数据验证数据进场用到,一般情况下我都用dos黑窗口进行操作, ...
- 分布式监控系统Zabbix-3.0.3-完整安装记录(1)
分布式监控系统Zabbix-3.0.3的安装记录 环境说明zabbix-server:192.168.1.30 #zabbix的服务端(若要监控本机,则需要配置本机的Zabbix agent, ...
- 微信小程序中的组件
前言 之前做小程序开发的时候,对于开发来说比较头疼的莫过于自定义组件了,当时官方对这方面的文档也只是寥寥几句,一笔带过而已,所以写起来真的是非常非常痛苦!! 好在微信小程序的库从 1.6.3 开始,官 ...
- idea 设置注释
idea和eclipse的注释还是有一些差别的. idea: 类头注释:打开file->setting->Editor->Filr and Code Templates->In ...
- javac编译提示错误需要为 class、interface 或 enum
HelloWorld.java:1: 需要为 class.interface 或 enum锘缝ublic class HelloWorld{^1 错误 这个错误出现的原因主要是在中文操作系统中,使用一 ...
- 链表数据结构(C/C++语言实现)
注意:没有使用malloc和free:加了一个头文件,用于清屏和暂停:还有就是一个错误特别容易被忽略,那就是主函数中声明了LinkList p,然后就直接创建链表,忘了给p分配空间.一定要先初始化链表 ...
- DELPHI 解决DBGrid SHIFT键多选问题
在实际项目中,偶然遇到需要按下SHIFT键,在DBGrid中进行多选的情况,测试了几种方法,最终确定了一个比较好的解决方法,总结如下: procedure TTestFrame.TestDBGridM ...