APIO模拟赛(HGOI20180909)
想法:贪心。
A.最大高度大的先剪
首先需要知道:
1.每个草最多剪1次
假设有个草剪了2次,显然可以放到最后一次剪得效果和剪2次的效果一样的,
为了少剪那么草最多剪去一次,从而,步数step>N就是impossible!
所以枚举步数,每次从后往前贪心取最大的高度,后剪
code 70pts:
# include <bits/stdc++.h>
using namespace std;
const int MAXN=;
bool cut[MAXN];
int g[MAXN],h[MAXN],r[MAXN],u[MAXN],n,H;
bool check(int step)
{
memcpy(r,h,sizeof(h));
u[]=;
for (int i=;i<=n;i++) r[i]+=step*g[i];
memset(cut,false,sizeof(cut));
for (int i=;i<=step;i++) {
int MAX=,P;
for (int j=;j<=n;j++)
if (r[j]>MAX&&cut[j]==false) MAX=r[j],P=j;
u[++u[]]=P;
cut[P]=true;
}
for (int i=;i<=step/;i++) swap(u[i],u[step-i+]);
memcpy(r,h,sizeof(h));
for (int i=;i<=step;i++) {
for (int j=;j<=n;j++) r[j]+=g[j];
r[u[i]]=;
int sum=;
for (int j=;j<=n;j++) sum+=r[j];
if (sum<=H) return true;
}
int sum=;
for (int i=;i<=n;i++) sum+=r[i];
if (sum<=H) return true;
else return false;
}
int main()
{
freopen("grass.in","r",stdin);
freopen("grass.out","w",stdout);
int T;scanf("%d",&T);
while (T--) {
scanf("%d%d",&n,&H);
for (int i=;i<=n;i++) scanf("%d",&h[i]);
for (int i=;i<=n;i++) scanf("%d",&g[i]);
int ans=-;
for (int i=;i<=n;i++)
if (check(i)) { ans=i; break; }
printf("%d\n",ans);
}
return ;
}
反例:
input:
3 6
12 1 1
1 4 4
output:
3
WA:
-1
100pts DP!!!
就是找出这样2条规律:
2.长得快的最后剪
这是显然的,如果长得快的先剪那么在后面剪一次长得慢的时候长得快的还在生长,
F[i][j]前i棵草,剪去j棵(此时过了j天),最大剪去高度
F[i][j]转移:
第i棵草剪去,F[i-1][j-1]+h[i] +g[i]*j //i-1棵剪去j-1棵加上这时候草的高度先长后剪H‘ = h[i]+g[i]*j
第i棵草不剪,F[i-1][j] 没有多余动作
方程: f[i][j]=max(f[i-1][j],f[i-1][j-1]+h[i]+g[i]*j);
AC code
# include <bits/stdc++.h>
# define Rint register int
using namespace std;
const int MAXN=;
int h[MAXN],g[MAXN],f[MAXN][MAXN];
int read()
{
int r=,num=; char ch=getchar();
if (ch=='-') ch=getchar(),r=-;
while (isdigit(ch)) num=num*+ch-'',ch=getchar();
return num*r;
}
int main()
{
freopen("grass.in","r",stdin);
freopen("grass.out","w",stdout);
int T=read();
while (T--) {
int n=read(),H=read();
int sumh=,sumg=;
for (Rint i=;i<=n;i++) h[i]=read(),sumh+=h[i];
for (Rint i=;i<=n;i++) g[i]=read(),sumg+=g[i];
memset(f,,sizeof(f));
for (Rint i=;i<=n-;i++)
for (Rint j=i+;j<=n;j++)
if (g[i]>g[j]) swap(g[i],g[j]),swap(h[i],h[j]);
for (Rint i=;i<=n;i++)
for (Rint j=;j<=i;j++)
f[i][j]=max(f[i-][j],f[i-][j-]+h[i]+g[i]*j);
int ans=-;
for (Rint i=;i<=n;i++)
if (sumh+sumg*i-f[n][i]<=H) { ans=i; break; }
printf("%d\n",ans);
}
return ;
}
Hint:题目出错:最后的条件改为A[i]-x<=B[j]<=A[i]+y;
想法:
50pts二分图匹配,按照题意模拟建边,匈牙利算法O(n2)轻松跑过
100pts运用单调性,知道A,B两个序列都是有序的,而x和y都是定值那么
满足的条件: A[i](单调递增) B[j](单调递增)
当B[j]不满足A[i]限制1的时候( B[j]>A[i]+y )B[j+1] 到B[m]都不符合
当B[j]不满足A[i]限制2的时候(B[j]<A[i]-x) B[1]到B[j]都不符合
那么贪心取最小的A[i]和B[j]就行
code 100pts (匈牙利和单调队列放一起了凑合着看看)
# include <bits/stdc++.h>
# define Rint register int
using namespace std;
const int MAXN=,MAXN2=;
bool mp[MAXN][MAXN],vis[MAXN];
int a[MAXN2],b[MAXN2],pre[MAXN];
int n,m,x,y,ans=;
bool find(int u)
{
for (Rint v=;v<=m;v++)
if (mp[u][v]&& !vis[v]) {
vis[v]=;
if (pre[v]==-||find(pre[v])) {
pre[v]=u;
return ;
}
}
return ;
}
void solve()
{
memset(pre,-,sizeof(pre));
for (Rint i=;i<=n;i++) {
memset(vis,false,sizeof(vis));
if (find(i)) ans++;
}
}
void work()
{
for (int i=;i<=n;i++) scanf("%d",&a[i]);
for (int i=;i<=m;i++) scanf("%d",&b[i]);
int i=,j=,ans=;
while (true) {
while (b[j]<a[i]-x&&j<=m) j++;
if (i>n||j>m) break;
if (b[j]<=a[i]+y) ans++,j++;
if (i>n||j>m) break;
i++;
}
printf("%d\n",ans);
}
int main()
{
freopen("match.in","r",stdin);
freopen("match.out","w",stdout);
scanf("%d%d%d%d",&n,&m,&x,&y);
if (n>MAXN) { work();return ; }
for (Rint i=;i<=n;i++) scanf("%d",&a[i]);
for (Rint i=;i<=m;i++) scanf("%d",&b[i]);
memset(mp,sizeof(mp),false);
for (Rint i=;i<=n;i++)
for (Rint j=;j<=m;j++)
if (a[i]-x<=b[j]&&b[j]<=a[i]+y) mp[i][j]=true;
solve();
printf("%d\n",ans);
return ;
}
【APIO2013】hahahahaha做什么?
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm> using namespace std; const int N = , M = , K = ; int n, m, k, cn = ;
long long ans = , maxL, ssize;
int cost[N], father[N], color[N];
long long size[N] = {}; long long get_max(long long a, long long b)
{
if (a > b) return a; else return b;
}
long long get_min(long long a, long long b)
{
if (a < b) return a; else return b;
} class Road
{
public :
int x, y, w, flag, ans;
Road (int x, int y, int w = , int flag = )
: x(x), y(y), w(w), flag(flag) {}
}; Road * road[M],
* road_sp[K]; class Node; class Edge
{
public :
Node * target;
Edge * next;
int flag;
/*Edge(Node * target, Edge * next, int flag) :
target(target), next(next), flag(flag) {};
~Edge()
{
if (next) delete next;
}*/
}; class Node
{
public :
Edge * head;
Node * father;
long long size, deep, flag;
/*
Node (long long size) :
size(size), head(0), father(0), deep(0), flag(0) {}
~Node()
{
if (head) delete head;
}
*/
}; Node * node[K]; Node * my_node[]; int my_node_count;
Edge * my_edge[]; int my_edge_count; Node * get_node(long long size)
{
Node * now = my_node[my_node_count ++];
now->size = size;
now->head = ;
now->father = ;
now->deep = ;
now->flag = ;
return now;
} Edge * get_edge(Node * target, Edge * next, int flag)
{
Edge * now = my_edge[my_edge_count ++];
now->target = target;
now->next = next;
now->flag = flag;
return now;
} void newedge(Node * x, Node * y, int flag)
{
Edge * e1 = get_edge(y, x->head, flag),
* e2 = get_edge(x, y->head, flag);
x->head = e1; y->head = e2;
} bool cmp_w(const Road * a, const Road * b)
{return a->w < b->w;} void init()
{
for (int i=; i<; i++)
{
my_edge[i] = new Edge();
my_node[i] = new Node();
}
scanf("%d%d%d", &n, &m, &k);
int x, y, w;
for (int i=; i<m; i++)
{
scanf("%d%d%d", &x, &y, &w);
road[i] = new Road(x, y, w);
}
for (int i=; i<k; i++)
{
scanf("%d%d", &x, &y);
road_sp[i] = new Road(x, y);
}
for (int i=; i<=n; i++)
scanf("%d", cost+i);
} int get_father(int x)
{
int head = x;
while (father[head] != head) head = father[head];
while (x != head)
{
int tmp = father[x];
father[x] = head;
x = tmp;
}
return head;
} void select()
{
sort(road, road+m, cmp_w);
for (int i=; i<=n; i++) father[i] = i;
for (int i=; i<m; i++)
{
int x = get_father(road[i]->x),
y = get_father(road[i]->y);
if (x != y)
{
road[i]->flag = ;
father[x] = y;
}
}
m = ;
for (int i=; m<n-; i++)
if (road[i]->flag) road[m++] = road[i];
} void check_select()
{
printf("m = %d\n", m);
for (int i=; i<m; i++)
printf("x = %d y = %d w = %d\n", road[i]->x, road[i]->y, road[i]->w);
} void build()
{
for (int i=; i<=n; i++) father[i] = i;
for (int i=; i<k; i++)
{
int x = get_father(road_sp[i]->x),
y = get_father(road_sp[i]->y);
if (x != y) father[x] = y;
}
for (int i=; i<m; i++)
{
int x = get_father(road[i]->x),
y = get_father(road[i]->y);
if (x != y)
father[x] = y;
else
road[i]->flag = ;
}
for (int i=; i<=n; i++) father[i] = i;
for (int i=; i<m; i++)
if (road[i]->flag)
{
int x = get_father(road[i]->x),
y = get_father(road[i]->y);
father[x] = y;
}
for (int i=; i<=n; i++)
if (father[i] == i)
color[i] = cn++;
for (int i=; i<=n; i++)
{
color[i] = color[get_father(i)];
size[color[i]] += cost[i];
}
m = ;
for (int i=; i<n-; i++)
if (!road[i]->flag) road[m++] = road[i];
} void check_build()
{
for (int i=; i<cn; i++)
{
printf("Color %d :", i);
for (int j=; j<=n; j++)
if (color[j] == i) printf("%d ", j);
printf(" size = %I64d\n", size[i]);
}
printf("sp edge:\n");
for (int i=; i<k; i++)
printf("x = %d y = %d\n", color[road_sp[i]->x], color[road_sp[i]->y]);
printf("other edge:\n");
for (int i=; i<m; i++)
printf("x = %d y = %d w = %d\n", color[road[i]->x], color[road[i]->y], road[i]->w);
} long long work(Node * & x, int w)
{
long long s = ;
if (x->flag)
{
//road_sp[x->flag-1]->ans = w;
s = x->size * w;
x->flag = ;
ssize -= x->size;
}
x = x->father;
return s;
} void dfs(Node * now)
{
for (Edge * e = now->head; e!=; e=e->next)
{
if (!e->target->deep)
{
e->target->deep = now->deep + ;
e->target->flag = e->flag;
e->target->father = now;
dfs(e->target);
if (e->flag) ssize += e->target->size;
now->size += e->target->size;
}
}
} void clear_road_sp()
{
for (int i=; i<k; i++) road_sp[i]->ans = ;
} void print_road_sp(long long s)
{
return ;
printf("%I64d ", s);
for (int i=; i<k; i++) printf("%d ", road_sp[i]->ans);
printf("\n", s);
} long long get_ans()
{
my_node_count = ;
my_edge_count = ;
for (int i=; i<cn; i++) node[i] = get_node(size[i]);
for (int i=; i<cn; i++) father[i] = i;
for (int i=; i<k; i++)
if (road_sp[i]->flag)
{
int x = get_father(color[road_sp[i]->x]),
y = get_father(color[road_sp[i]->y]);
if (x == y) return ;
father[x] = y;
newedge(node[color[road_sp[i]->x]], node[color[road_sp[i]->y]], i+);
}
maxL = ;
for (int i=; i<m; i++)
{
int x = get_father(color[road[i]->x]),
y = get_father(color[road[i]->y]);
if (x != y)
{
road[i]->flag = ;
father[x] = y;
newedge(node[color[road[i]->x]], node[color[road[i]->y]], );
}
else
{
if (road[i]->w > maxL) maxL = road[i]->w;
road[i]->flag = ;
}
} node[color[]]->deep = ;
ssize = ;
dfs(node[color[]]);
long long s = ;
//clear_road_sp();
for (int i=; i<m; i++)
{
if (ssize * maxL + s < ans) break;
if (road[i]->flag)
{
Node * x = node[color[road[i]->x]],
* y = node[color[road[i]->y]];
int c = ;
while (x != y)
if (x->deep > y->deep) s += work(x, road[i]->w); else s += work(y, road[i]->w);
}
}
//if (ssize != 0) printf("A = %I64d\n", ssize);
//print_road_sp(s);
for (int i=; i<=cn; i++) delete node[i];
return s;
} void dfs(int now)
{
if (now == k)
{
ans = get_max(get_ans(), ans);
return ;
}
road_sp[now]->flag = ;
dfs(now+);
road_sp[now]->flag = ;
dfs(now+);
} int main()
{
freopen("toll.in", "r", stdin);
freopen("toll.out", "w", stdout);
init();
select();
//check_select();
build();
//check_build();
dfs(); cout << ans << endl;
return ;
}
APIO模拟赛(HGOI20180909)的更多相关文章
- Shallwe学长的模拟赛
NOIP Simulated Test 这个名字一听就很高端. T1:sGCD:http://uoj.ac/problem/48 题意概述:给定一个长度为$n$的序列,求$sgcd(a_1,a_i)$ ...
- NOIP模拟赛20161022
NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...
- NOI模拟赛 Day1
[考完试不想说话系列] 他们都会做呢QAQ 我毛线也不会呢QAQ 悲伤ING 考试问题: 1.感觉不是很清醒,有点困╯﹏╰ 2.为啥总不按照计划来!!! 3.脑洞在哪里 4.把模拟赛当作真正的比赛,紧 ...
- NOIP第7场模拟赛题解
NOIP模拟赛第7场题解: 题解见:http://www.cqoi.net:2012/JudgeOnline/problemset.php?page=13 题号为2221-2224. 1.car 边界 ...
- contesthunter暑假NOIP模拟赛第一场题解
contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...
- NOIP模拟赛 by hzwer
2015年10月04日NOIP模拟赛 by hzwer (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...
- 小奇模拟赛9.13 by hzwer
2015年9月13日NOIP模拟赛 by hzwer (这是小奇=> 小奇挖矿(explo) [题目背景] 小奇要开采一些矿物,它驾驶着一台带有钻头(初始能力值w)的飞船,按既定路线依次飞 ...
- PKUSC 模拟赛 day1 下午总结
下午到了机房之后又困又饿,还要被强行摁着看英文题,简直差评 第一题是NOIP模拟赛的原题,随便模拟就好啦 本人模拟功力太渣不小心打错了个变量,居然调了40多分钟QAQ #include<cstd ...
- [GRYZ]寒假模拟赛
写在前面 这是首次广饶一中的OIERS自编自导,自出自做(zuo)的模拟赛. 鉴于水平气压比较低,机(wei)智(suo)的WMY/XYD/HYXZC就上网FQ下海找了不少水(fei)题,经过他们优( ...
随机推荐
- 对寄存器ESP和EBP的一些理解
PS:EBP是当前函数的存取指针.即存储或者读取数时的指针基地址:ESP就是当前函数的栈顶指针. 每一次发生函数的调用(主函数调用子函数)时,在被调用函数初始时,都会把当前函数(主函数)的EBP压栈, ...
- Java是如何读到hbase-site.xml 的内容的
Java是如何读到hbase-site.xml 的内容的 Java客户端使用的配置信息是被映射在一个HBaseConfiguration 实例中. HBaseConfiguration有一个工厂方法, ...
- 20155204 王昊《网络对抗技术》EXP1 PC平台逆向破解
20155204 王昊<网络对抗技术>EXP1 PC平台逆向破解 (一)实验内容 一.掌握NOP.JNE.JE.JMP.CMP汇编指令的机器码 NOP:NOP指令即"空指令&qu ...
- 20155301 Web基础
20155301 Web基础 1.基础问题回答 (1)什么是表单 答: 表单是一个包含表单元素的区域. 表单元素是允许用户在表单中(比如:文本域.下拉列表.单选框.复选框等等)输入信息的元素 (2)浏 ...
- 2017-2018-2 20155333 《网络对抗技术》 Exp1 PC平台逆向破解
2017-2018-2 20155333 <网络对抗技术> Exp1 PC平台逆向破解 1. 逆向及Bof基础实践说明 1.1 实践目标 本次实践的对象是一个名为pwn1的linux可执行 ...
- source insight之quicker.em宏的使用
source insight有很多宏可以用,这里介绍的宏是quicker.em这个宏,它是华为的一个员工写的,很实用. 1.安装quicker.em宏 一.打开base这个工程Project-> ...
- linux chroot 命令
chroot,即 change root directory (更改 root 目录).在 linux 系统中,系统默认的目录结构都是以 /,即以根 (root) 开始的.而在使用 chroot 之后 ...
- [ERROR] Failed to execute goal net.alchim31.maven:scala-maven-plugin:3.2.2:compile (scala-compile-first) on project spark-tags_2.11: Execution scala-compile-first of goal net.alchim31.maven:scala-mave
build/mvn -Pkubernetes -Phadoop-2.7 -Dhadoop.version=2.7.3 -Phive -Phive-thriftserver -DskipTests cl ...
- Yaml学习文档
pdf文档地址 http://yaml.org/spec/ JS-Yaml demo地址 http://nodeca.github.io/js-yaml/
- 李群与李代数在slam中的应用
昨天,刚接触道了李群和李代数,查了许多资料,也看了一些视屏.今天来谈谈自己的感受. 李群是有一个挪威数学家提出的,在十九二十世纪得到了很大的发展. 其归于非组合数学,现在简单介绍李群和李代数的概念.群 ...