T1 题意:你要进行n次操作,第i次选择一个数k∈[1,i],并插入到当前序列的第k个位置。给定目标序列,输出操作序列。100,2s。

解:冷静分析一波,我们可以从后往前确定操作序列。这样每次确定一个操作之后就会删除一个数。

如果有ai = i的位置那我们显然可以把这个i操作放到操作序列最后。如果有多个这样的i,从后往前处理。

 #include <bits/stdc++.h>

 const int N = ;

 int a[N], b[N];

 int main() {

     int n;
scanf("%d", &n);
for(int i = ; i <= n; i++) {
scanf("%d", &b[i]);
}
for(int i = n; i >= ; i--) {
bool f = ;
for(int j = i; j >= ; j--) {
if(b[j] > j) break;
if(b[j] == j) {
a[i] = j;
//printf("a %d = %d \n", i, j);
for(int k = j; k < i; k++) {
b[k] = b[k + ];
}
f = ;
break;
}
}
if(!f) {
printf("-1");
return ;
}
}
for(int i = ; i <= n; i++) {
printf("%d\n", a[i]);
}
return ;
}

AC代码

T2 题意:构建一个n个点的简单无向连通图,使得每个点的邻居的编号之和相等。100,2s。

解:先玩一下3和4的时候,发现是一张完全二分图,且左右部的节点编号之和相等。

这启发我们把这些点分成k份,每份的编号之和相同。然后每个点向其他所有不是同类的点连边。

n为偶数的时候就是首尾配对,和为n + 1,n为奇数的时候提出n来然后首尾配对,和为n。

 #include <bits/stdc++.h>

 const int N = ;

 int vis[N];

 int main() {

     int n, cnt1 = ;
scanf("%d", &n);
int t = (n + ) * n / ;
if(t & ) {
if((n & ) == ) {
printf("%d\n", n * (n - ) / );
for(int i = ; i <= n; i++) {
for(int j = i + ; j <= n; j++) {
if(i + j != n + ) {
printf("%d %d \n", i, j);
}
}
}
return ;
}
else {
printf("%d \n", (n - ) * (n - ) / + n - );
for(int i = ; i < n; i++) {
printf("%d %d \n", i, n);
}
for(int i = ; i < n; i++) {
for(int j = i + ; j < n; j++) {
if(i + j != n) {
printf("%d %d \n", i, j);
}
}
}
}
return ;
}
t /= ;
for(int i = n; i >= && t; i--) {
if(t >= i) {
t -= i;
vis[i] = ;
cnt1++;
}
}
printf("%d\n", cnt1 * (n - cnt1));
for(int i = ; i <= n; i++) {
if(vis[i]) {
for(int j = ; j <= n; j++) {
if(!vis[j]) {
printf("%d %d \n", i, j);
}
}
}
} return ;
}

AC代码

T3 题意:给定简单无向连通图,问是否能把所有边分成三个环。点可以重复经过。10w,10w,2s。

解:这TM居然是分类讨论...首先有度数为奇的肯定不行。然后只要排除一种情况:总环数 < 3即可。

因为如果环比较多,任意两个相邻(共用某一点)的环肯定能合二为一的......

如果有某个点的度数大于4,肯定合法。如果没有点的度数大于2,肯定不合法。

当点的度数最大为4的时候,可以把其他所有度数为2的点缩成某些边。

如果只有一个点的度数为4,相当于该点有两条自环,不行。

如果有两个点的度数为4,有一种特殊情况不合法:

其余情况和有大于2个点的度数等于4的时候,均合法。

 #include <bits/stdc++.h>

 const int N = ;

 struct Edge {
int nex, v;
}edge[N << ]; int tp = ; int e[N], n, m, in[N], vis[N], stk[N], top, cnt, A, B; inline void add(int x, int y) {
tp++;
edge[tp].v = y;
edge[tp].nex = e[x];
e[x] = tp;
return;
} void DFS(int x, int f) {
if(f && x == A) {
puts("Yes");
exit();
}
else if(x == B) return;
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(y != f) DFS(y, x);
}
return;
} int main() {
scanf("%d%d", &n, &m);
for(int i = , x, y; i <= m; i++) {
scanf("%d%d", &x, &y);
add(x, y);
add(y, x);
in[x]++;
in[y]++;
}
int largeIn = , cnt = ;
for(int i = ; i <= n; i++) {
if(in[i] & ) {
puts("No");
return ;
}
if(largeIn < in[i]) {
largeIn = in[i];
cnt = ;
}
else if(largeIn == in[i]) {
cnt++;
}
}
if(largeIn > ) {
puts("Yes");
return ;
}
else if(largeIn == && cnt > ) {
puts("Yes");
return ;
}
else if(largeIn == && cnt == ) {
for(int i = ; i <= n; i++) {
if(in[i] == ) {
if(!A) A = i;
else {
B = i;
break;
}
}
}
DFS(A, );
}
puts("No");
return ;
}

AC代码

T4 题意:给定一个排列。你可以花费A使一个区间最左边的数跑到最右边,其余区间内的数左移。也可以花费B来进行逆操作。求使其变成升序的最小代价。5000,2s。

解:神仙DP。

显然有个n3的区间DP是设f[l][r]表示把[l, r]这一段排序。转移的时候一段区间可以由两个子区间拼起来,也可以找到其中最值然后挪一次。

正解全然不同......我们只注重这些元素的相对位置,也就是说下标可以为实数。

然后考虑每次操作等价于把一个数往旁边挪,别的数不变。

然后考虑最优解肯定是若干个数往左,若干个数往右,若干个数不动。我们以那些不动的数来DP。

设f[i][j]表示值域前i个数全部排好序了,且最大的那个不动的数是j,且比j大的数全部聚集在(j, j + 1)这一段的最小代价。

考虑f[i][j]是怎么得来的:如果当前这个数i初始时在j的左边,那么一定要往右移(i比j大)。反之一定要往左移(聚集到(j, j + 1)中)。

然后我们忽了一种转移:i在j右边的时候也可以不移动!此时f[i][i] = f[i - 1][j]

然后就完事了。

 #include <bits/stdc++.h>

 typedef long long LL;
const int N = ; LL f[N][N];
int a[N], p[N]; int main() { int n;
LL A, B;
scanf("%d%lld%lld", &n, &A, &B);
for(int i = ; i <= n; i++) {
scanf("%d", &a[i]);
p[a[i]] = i;
}
memset(f, 0x3f, sizeof(f));
/// DP
f[][] = ;
for(int i = ; i <= n; i++) {
for(int j = ; j < i; j++) {
/// f[i][j]
/*for(int k = 0; k < i; k++) {
/// f[i][j] <- f[i - 1][k]
if(p[i] < p[k]) {
f[i][j] = std::min(f[i][j], f[i - 1][k] + A);
}
else {
f[i][j] = std::min(f[i][j], f[i - 1][k] + B);
}
}*/
if(p[i] < p[j]) {
f[i][j] = f[i - ][j] + A;
}
else {
f[i][j] = f[i - ][j] + B;
f[i][i] = std::min(f[i][i], f[i - ][j]);
}
}
/*for(int j = 0; j <= i; j++) {
printf("%3lld ", f[i][j]);
}
puts("");*/
} LL ans = 4e18;
for(int i = ; i <= n; i++) {
ans = std::min(ans, f[n][i]);
}
printf("%lld\n", ans);
return ;
}

AC代码

T5 题意:给定序列,把它们两两配对使得每一对的和 % MO的最大值最小。10w,1e9,2s。

解:排序之后考虑最优方案长什么样。

然后发现它们一定长这样...因为不满足这样的方案调整成这样一定更优。

枚举分界点是n2的,但是发现分界点越靠左越优,于是二分这个分界点,使其满足条件(左边的和全小于MO,右边全不小于MO),然后一次得出答案。

单调性:就考虑若分界点在a和b都满足条件,那么a,b之间的任一点也满足条件。比b小所以左边满足,比a大所以右边满足。

 #include <bits/stdc++.h>

 const int N = ;

 int a[N], MO, n;

 inline bool check(int p) {
int l = p + , r = n;
while(l < r) {
if(a[l] + a[r] < MO) return false;
l++;
r--;
}
return true;
} int main() {
scanf("%d%d", &n, &MO);
n <<= ;
for(int i = ; i <= n; i++) {
scanf("%d", &a[i]);
}
std::sort(a + , a + n + ); int l = n, r = n; /// [1, l] (l, r]
while(a[n] + a[l - ] >= MO && l >= ) l -= ;
while(a[] + a[r] >= MO && r >= ) r -= ;
l /= ;
r /= ; while(l < r) {
int mid = (l + r) >> ;
if(check(mid * )) r = mid;
else l = mid + ;
} int p = r * ;
int ans = ;
l = , r = p;
while(l < r) {
ans = std::max(ans, a[l] + a[r]);
l++;
r--;
}
l = p + , r = n;
while(l < r) {
ans = std::max(ans, (a[l] + a[r]) % MO);
l++;
r--;
}
printf("%d\n", ans);
return ;
}

AC代码

agc032的更多相关文章

  1. 【AtCoder】AGC032

    AGC032 A - Limited Insertion 这题就是从后面找一个最靠后而且当前可以放的,可以放的条件是它的前面正好放了它的数值-1个数 如果不符合条件就退出 #include <b ...

  2. 【Atcoder】 AGC032赛后总结

    比赛前 emmm,今天是场AGC,想起上次我的惨痛经历(B都不会),这次估计要凉,可能A都不会Flag1 比赛中 看场看了波\(A\),咦,这不是很呆的题目吗?倒着扫一遍就好了. 然后切了就开始看B, ...

  3. AtCoder整理(持续更新中……)

    做了那么久的atcoder觉得自己的题解发的很乱 给有想和我一起交流atcoder题目(或者指出我做法的很菜)(或者指责我为什么整场比赛只会抄题解)的同学一个索引的机会??? 于是写了个爬虫爬了下 A ...

  4. 【做题记录】AtCoder AGC做题记录

    做一下AtCoder的AGC锻炼一下思维吧 目前已做题数: 75 总共题数: 239 每一场比赛后面的字母是做完的题,括号里是写完题解的题 AGC001: ABCDEF (DEF) AGC002: A ...

  5. AtCoder AGC032E Modulo Pairing (二分、贪心与结论)

    题目链接 https://atcoder.jp/contests/agc032/tasks/agc032_e 题解 猜结论好题. 结论是: 按\(a_i\)从小到大排序之后,一定存在一种最优解,使得以 ...

  6. AtCoder AGC032D Rotation Sort (DP)

    题目链接 https://atcoder.jp/contests/agc032/tasks/agc032_d 题解 又是一道神仙题啊啊啊啊...atcoder题真的做不来啊QAQ 第一步又是神仙转化: ...

随机推荐

  1. centos7之vm11添加网卡

    需求 根据实际需求原来有一块网卡,现在需要新加一块网卡做集群. 1.在虚拟机添加一块网卡,开机后ip a查看是不是新加了一块网卡,下图是为了讲解,其实已经是做完的状态. 2.上满我们看到新加了一块网卡 ...

  2. Spring标签之Bean @Scope

    @Bean 的用法 @Bean是一个方法级别上的注解,主要用在@Configuration注解的类里,也可以用在@Component注解的类里.添加的bean的id为方法名 定义bean 下面是@Co ...

  3. LODOP暂存、应用、复原 按钮的区别

    LODOP中打印设计(PRINT_DESIGN)有暂存和复原按钮,打印维护(PRINT_SETUP)有应用和复原按钮. 打印设计暂存和打印维护的应用功能不同,两者的区别:1.打印设计的暂存.复原(类似 ...

  4. Python学习之路————Day03

    今日内容: 1.IDE开发环境的安装 2.基本数据类型的使用 3.运算符 一. 算术运算符: 比较运算符 赋值运算符 逻辑运算符 身份运算符:is比较的是id 而==比较的是值 二.基本数据类型 为什 ...

  5. PCIE

    ---恢复内容开始--- 高速差分总线.串行总线 每一条PCIe链路中只能连接两个设备这两个设备互为是数据发送端和数据接收端.PCIe链路可以由多条Lane组成,目前PCIe链路×1.×2.×4.×8 ...

  6. Tunnel Warfare(线段树取连续区间)

    emmmmmmmm我菜爆了 思路来自:https://blog.csdn.net/chudongfang2015/article/details/52133243 线段树最难的应该就是要维护什么东西 ...

  7. 趣味网站5个,小鸡词典/中国配色/名著地图/海洋之音/LOGO设计

    一.小鸡词典 很多流行的词语还没有收录到各大词典,却可以在小鸡词典搜索到,小鸡词典是最全的网络流行词语词典. 不少词条搞笑无厘头,撰写词条还会获得红包. 访问地址:https://jikipedia. ...

  8. Go语言函数相关

    1.函数的声明定义 //func关键字 //getStudent函数名 //(id int, classId int) 参数列表 //(name string,age int) 返回值列表 func ...

  9. Vmware 给虚拟机传脚本并执行

    #_*_ coding:utf8 _*_ from pysphere import VIServer import ssl import re import sys import os import ...

  10. P1130 红牌

    题目描述 某地临时居民想获得长期居住权就必须申请拿到红牌.获得红牌的过程是相当复杂 ,一共包括NN个步骤.每一步骤都由政府的某个工作人员负责检查你所提交的材料是否符合条件.为了加快进程,每一步政府都派 ...