https://www.xoj.red/contests/show/1231

下面会写一些题目的解析什么的,当然不会粘贴题目只是简单提一下

(部分题目简单的题目就不概括了)

其实难度应该前面比较低.

问题A: 3894: Out of Sorts

本题求出冒泡排序需要几趟。

考虑一次冒泡排序的交换,减小对应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

问题B: 3895: Lemonade Line

考虑一个简单的贪心,每次选择当前等待奶牛数目最多的一个,占用等待奶牛数少的奶牛的位置。

如果不是这样做,对答案会有正贡献,是我们不期望的,与答案最优性矛盾,我们选择一个一定是最优的决策。

# 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

问题C: 3896: Multiplayer Moo

大概是不存在一个正解的。

问题D: 3897: Out of Sorts

考虑这样一个事情,如果正反来了一边那么每一次对于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

问题E: 3898: Milking Order

本题要求最大化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

问题F: 3899: Talent Show

考虑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

问题G: 3900: Out of Sorts

我们不妨宏观考虑这个排序的问题,在对于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

问题I: 3902: Disruption

这个题目非常有价值,我想专门开一个blog讲一讲这个题。

https://www.cnblogs.com/ljc20020730/p/10467324.html

欢迎支持!!!

【杂题1】USACO 2018 Open Contest-练习的更多相关文章

  1. [USACO 2018 December Contest]作业总结

    t1 Convention 题目大意 每一头牛都有一个来的时间,一共有\(n\)辆车,求出等待时间最长的那头牛等待的最小时间. 解法 第一眼看到这道题还以为是\(2018noip\)普及组的t3魔鬼题 ...

  2. [USACO 2018 Open Contest]作业总结

    t1-Out of Sorts 题目大意 将最大的数冒泡排序到最后需要多少次操作. 分析 排序后判断距离. ac代码 #include<bits/stdc++.h> #define N 1 ...

  3. 【二分+拓扑排序】Milking Order @USACO 2018 US Open Contest, Gold/upc_exam_6348

    目录 Milking Order @USACO 2018 US Open Contest, Gold/upc_exam_6348 PROBLEM 题目描述 输入 输出 样例输入 样例输出 提示 MEA ...

  4. 【USACO 2019 Feburary Contest】Gold

    模拟二月金组,三个半小时AK. USACO 2019 Feburary Contest, Gold T1 题意:给定一棵树,每个点有点权,每次可以进行以下操作之一: 更改一个点的点权 求某条路径上的点 ...

  5. [USACO 2018 Feb Gold] Tutorial

    Link: USACO 2018 Feb Gold 传送门 A: $dp[i][j][k]$表示前$i$个中有$j$个0且末位为$k$的最优解 状态数$O(n^3)$ #include <bit ...

  6. 贪心/构造/DP 杂题选做Ⅲ

    颓!颓!颓!(bushi 前传: 贪心/构造/DP 杂题选做 贪心/构造/DP 杂题选做Ⅱ 51. CF758E Broken Tree 讲个笑话,这道题是 11.3 模拟赛的 T2,模拟赛里那道题的 ...

  7. COCI 2018/2019 CONTEST #2 T4 Maja T5Sunčanje Solution

    COCI 2018/2019 CONTEST #2 T4 T5 Solution abstract 花式暴力 #2 T5 Sunčanje 题意 按顺序给你1e5个长方形(左下角坐标&& ...

  8. [USACO 2018 Jan Gold] Tutorial

    Link: USACO 2018 Jan Gold 传送门 A: 对于不同的$k$,发现限制就是小于$k$的边不能走 那么此时的答案就是由大于等于$k$的边形成的图中$v$所在的连通块除去$v$的大小 ...

  9. 正睿OI DAY3 杂题选讲

    正睿OI DAY3 杂题选讲 CodeChef MSTONES n个点,可以构造7条直线使得每个点都在直线上,找到一条直线使得上面的点最多 随机化算法,check到答案的概率为\(1/49\) \(n ...

  10. dp杂题(根据个人进度选更)

    ----19.7.30 今天又开了一个新专题,dp杂题,我依旧按照之前一样,这一个专题更在一起,根据个人进度选更题目; dp就是动态规划,本人认为,动态规划的核心就是dp状态的设立以及dp转移方程的推 ...

随机推荐

  1. css-文本左右对齐

    1.给目标元素加 display:block;text-align:justify; 2.如果最后一行没充满整行,因为text-align:justify,所以字字之间会有间隔,应给目标元素加伪类,添 ...

  2. python语言程序设计8

    1, 说实话,我挺伤心的,感觉  有点像烂剧里的主演...也许我早几天明白的话,会不会结果会不一样?但是之前还真没往这方面想过,但是确实是开了一个口子了,也不急吧.努力把现在的事给做好,变帅变高,那很 ...

  3. UPC-5063-二分图最大匹配

    好吧二分图的最小点覆盖=最大匹配 这道题也就变成模板题了... 写一个提醒,在写二分图时,尽量清零操作清空为-1,比如这个题,匹配数组girl[]如果清空为0,代表每个点都与0点连接,但是实际上是并没 ...

  4. cordova打包webapp

    cordova打包webapp 在项目开发中,需要将h5页面打包成app,这个时候我们可以使用cordova来打包.在官方文档中,我们可以了解到创建一个app十分简单,你的电脑上有nodejs就行,我 ...

  5. D. Too Easy Problems

    链接 [http://codeforces.com/group/1EzrFFyOc0/contest/913/problem/D] 题意 给你n个题目,考试时间T,对于每个问题都有一个ai,以及解决所 ...

  6. 在Java中执行Tomcat中startup.bat

    问题:更改数据库时,需要重启Tomcat服务器,才能把更改后的数据加载到项目中.于是想每次更改数据库时,都调用Java方法,重启Tomcat 代码: Process process = Runtime ...

  7. 广商博客冲刺第三天new

    第二天沖刺傳送門 第三四天沖刺傳送門 这一天我们主要是弄网页前台设计跟框架设计,这方面主要是由张奇聪负责.我们在amaze ui,smart ui,angularjs+bootstrap中挑选,最终选 ...

  8. Java面向对象(Eclipse高级、类与接口作为参数返回值)

      面向对象 今日内容介绍 u Eclipse常用快捷键操作 u Eclipse文档注释导出帮助文档 u Eclipse项目的jar包导出与使用jar包 u 不同修饰符混合使用细节 u 辨析何时定义变 ...

  9. Docker for windows 入门一(下载安装)

    预安装条件,可以查阅官方文档,本人是Win10 x64(必要条件)教育版+开启Hyper-V(Feature特性),具体可参考云栖社区的文章: https://yq.aliyun.com/articl ...

  10. mysql复杂查询

    所谓复杂查询,指涉及多个表.具有嵌套等复杂结构的查询.这里简要介绍典型的几种复杂查询格式. 一.连接查询 连接是区别关系与非关系系统的最重要的标志.通过连接运算符可以实现多个表查询.连接查询主要包括内 ...