之前都没做出来的同名题简直留下心理阴影啊...其实这道题还是挺好想的QAQ

可以发现,鸟可以走到的点是如下图这样扩展的:

由$(0,0)$向两边扩展,黑色是可以扩展到的点,红色是不能扩展的点,可以推出,在扩展的区间内,横纵坐标奇偶性相同的点就可以被扩展到,反之则一定不可以。

接下来看有柱子的情况:

可以发现,遇到柱子时,可行的区域就变成了与柱子的区域取交集,然后接着向后扩展,直到遇到下一个柱子。

我们最后要找的实际上就是横坐标为$m$时可行区域的下界,可以证明到下界按的次数一定是最少的。而求到一个点需要按的次数就直接用$(x+y)/2$就可以叻。

【注意】当当前范围左右端点不可行时要缩小范围。

#include<iostream>
#include<cstdio>
using namespace std; long long read ( long long & x ) {
x = ; char ch = getchar ( ); int t = ;
while ( ch > '' || ch < '' ) { if ( ch == '-' ) t = -; ch = getchar ( ); }
while ( ch >= '' && ch <= '' ) { x = x * + ch - ''; ch = getchar ( ); }
x = x * t;
} long long p, q, m, n;
long long pos[], b[], c[], L[], R[];
int main ( ) {
freopen ( "bird.in", "r", stdin );
freopen ( "bird.out", "w", stdout );
scanf ( "%lld%lld%lld%lld", &p, &q, &m, &n );
for ( int i = ; i <= n; i ++ )
read ( pos[i] ), read ( b[i] ), read ( c[i] );
if ( q - p == ) {
printf ( "-1" ); return ;
}
int i;
long long l, r;
for ( i = ; i <= n && pos[i] <= m; i ++ ) {
L[i] = L[i-] - ( pos[i] - pos[i-] );
R[i] = R[i-] + ( pos[i] - pos[i-] );
L[i] = max ( b[i] + , L[i] );
R[i] = min ( c[i] - , R[i] );
if ( pos[i] % ) {
if ( L[i] % == ) L[i] += ;
if ( R[i] % == ) R[i] -= ;
} else {
if ( L[i] % ) L[i] += ;
if ( R[i] % ) R[i] -= ;
}
if ( L[i] > R[i] ) { printf ( "-1" ); return ; }
}
i --;
l = L[i] - ( m - pos[i] );
r = R[i] + ( m - pos[i] );
l = max ( p + , l );
r = min ( q - , r );
if ( m % ) {
if ( l % == ) l += ;
if ( r % == ) r -= ;
} else {
if ( l % ) l += ;
if ( r % ) r -= ;
}
if ( l > r ) { printf ( "-1" ); return ; }
else printf ( "%lld", ( l + m ) >> );
return ;
}

关于按位运算的总是和$Trie$树有关啊...

可是考场上怎么也想不到怎么利用$Trie$树处理最小生成树。

最后发现原理其实还是挺简单的,就是代码实现...(最后用自己的写法$A$掉叻简直无敌激动啊!!

首先把所有数建成一棵$Trie$树,如下:

上图表示了1到7的所有数(统一位数后),可以发现,在叶子节点位置的相邻两个相连一定是当前最优的连法,因为这样连的代价一定是1:

于是现在要向上走合并两个子树:

比如合并如上子树时,实际上是要在两个子树中各找一个数,使这两个树的异或值是当前最小的。而且合并相邻两个子树一定比跳子树合并要优,相当于保证了前面位数一样,只看后面不一样的部分,相邻的子树前面一样的部分一定是最优的。

于是问题转换为如何快速在两个子树中找到异或值最小的两个数。暴力就是$n^2$复杂度。

然后我们想到如果是给定一个值,要在一个$Trie$树上找到与之异或起来最小的树,就是沿着$Trie$树,按位往最优的走就可以了,复杂度是$log_{位数}$。

所以回到题上,我们可以遍历一个子树的所有数,在另外一个子树上$log$查找最优解,成功将复杂度简化为$nlog_n$。

在此我采用$dfs$遍历子树(选择遍历的子树是$size$小的那一个),根据深度来判断是否到底和在路上计算异或。

(自己写出来还是挺感动的55555

(尝试了一下新的代码风格

#include<bits/stdc++.h>
using namespace std; int n, a[]; int son[][], tail;
long long ans, vmin;
int siz[], dep[];
void build(int x, int id) {
int u = ;
int t = ;
while(t >= ) {
int now = ( x >> t ) & ;
if(!son[u][now]) {
son[u][now] = ++tail;
siz[u] ++;
dep[tail] = t;
}
u = son[u][now];
t --;
}
return;
} long long query(long long val, int nd, long long now) {
if(!dep[nd]) return now;
int t = (val >> (dep[nd] - )) & ;
if(son[nd][t]) return query(val, son[nd][t], now << );
else return query(val, son[nd][t^], now << | );
} void Find(int nd, long long val, int rs) {
if(!dep[nd]) { vmin = min(vmin, query(val, rs, )); return; }
if(son[nd][]) Find(son[nd][], val << , rs);
if(son[nd][]) Find(son[nd][], val << | , rs);
} void Dfs ( int u ) {
int ls = son[u][], rs = son[u][];
if(ls) Dfs(ls);
if(rs) Dfs(rs);
if(!ls || !rs) return;
if(siz[ls] > siz[rs]) swap(ls, rs);
vmin = 0x3f3f3f3f;
Find(ls, ls == son[u][], rs);
ans += vmin;
} int main ( ) {
freopen("road.in", "r", stdin);
freopen("road.out", "w", stdout);
scanf("%d", &n);
for ( int i = ; i <= n; i ++ ) {
scanf("%d", &a[i]);
build(a[i], i);
}
Dfs();
printf("%lld", ans);
return ;
}

这是我在考试中见过最长的题干了...

(所以当然不会改的,以下是$std$133行代码%%%

(真的是不能接受这种抽象的码风!!

#define FIO "code"
#include <cstdio>
#include <cctype>
#define L_MAX 112640
#define O_MAX 55
#define N_MAX 56
#define C_MAX 127
inline bool is_name(int c)
{
return isalnum(c) || c == '_' || c == '$';
}
char a[L_MAX + ],
* i = a, * j = i, * k = a, * l = k; // [i, j): last word; [k, l): current word
const char * op[O_MAX] = {
"((", "))", "[[", "[<:", "]]", "]:>", "{{", "{<%", "}}", "}%>",
"##", "#%:", "..", "!!", "~~", ",,", ";;",
"++", "=+=", "+++", "--", "=-=", "---", "**", "=*=",
"&&", "=&=", "&&&", "||", "=|=", "|||", "^^", "=^=",
"<<", "=<=", "<<<", "=<<=", ">>", "=>=", ">>>", "=>>=",
"==", "===", "=!=", "??", "::", ":::",
"''", "\"\"", "//", "=/=", "c//", "C/*", "%%", "=%=",
};
int n = , trie[N_MAX + ][C_MAX], type[N_MAX + ],
r, // is forced to break line?
s, t; // type of [i, j), [k, l); [0] => empty, [1] => name, [c] => type
inline void insert(int t, const char * s)
{
static int u;
for (u = ; *s; u = trie[u][int(*s++)])
if (!trie[u][int(*s)]) trie[u][int(*s)] = ++n;
type[u] = t;
}
inline bool check()
{
return s == ' ' || (s == && t == ) || (s == '/' && (*k == '/' || *k == '*')) || (s == ':' && *k == ':') || (s == '+' && *k == '+') || (s == '-' && *k == '-') || (s == '<' && *k == '<') || (s == '>' && *k == '>') || (s == '&' && *k == '&') || (s == '<' && *k == ':') || (s == '%' && *k == ':') || (s == && t == '"' && j != k && ((j - i == && (*i == 'u' || *i == 'U' || *i == 'L')) || (j - i == && *i == 'u' && *(i + ) == '')));
}
inline void output(int c = )
{
if (c) putchar(c);
i = k, j = l, s = t;
while (k < l) putchar(*k++);
}
inline char seek(char * l)
{
while (*l == '\\' && !*(l + )) gets(l);
return *l;
}
inline void seek_char(char *& l)
{
for (seek(l); *l != '\''; seek(++l))
if (*l == '\\') seek(++l);
++l;
}
inline void seek_str(char *& l)
{
for (seek(l); *l != '"'; seek(++l))
if (*l == '\\') seek(++l);
++l;
}
inline void seek_comment_line(char *& l)
{
for (seek(l); *l; seek(++l));
}
inline void seek_comment_block(char *& l)
{
do
{
++l;
while (!seek(l))
*l++ = '\n', gets(l);
seek(l);
}
while (*l != '/' || *(l - ) != '*');
++l;
}
inline int seek_word(char *& k, char *& l)
{
static int t, u;
do
{
k = l;
while (isspace(seek(k)))
++k;
if (!*(l = k))
t = ;
else if (is_name(*l)) // names | numbers
for (t = , ++l; is_name(seek(l)); ++l);
else
{
for (u = ; seek(l) && trie[u][int(*l)]; u = trie[u][int(*l++)]);
t = type[u];
switch (t)
{
case '\'': seek_char(l); break;
case '"': seek_str(l); break;
case 'c': seek_comment_line(l); break;
case 'C': seek_comment_block(l); break;
}
}
}
while (t == 'c' || t == 'C');
return t;
}
int main()
{
freopen(FIO ".in", "r", stdin);
freopen(FIO ".out", "w", stdout);
for (int o = ; o < O_MAX; ++o)
insert(*op[o], op[o] + );
r = '^';
while (gets(l))
{
if (r == '\n') putchar('\n'), r = s = , i = j;
t = seek_word(k, l);
if (k == l)
continue;
else if (t != '#')
output(check() ? ' ' : );
else
{
output(s == ? : '\n');
r = '\n', t = seek_word(k, l), output();
if (*i == 'd') // is #define?
{
t = seek_word(k, l), output(' ');
if (seek(l) != '(') s = ' ';// is function-like macro?
}
}
while ((t = seek_word(k, l)))
output(check() ? ' ' : );
}
return ;
}

【9.15校内测试】【寻找扩展可行域+特判】【Trie树 异或最小生成树】【模拟:)】的更多相关文章

  1. 【8.15校内测试】【队列】【manacher】

    dp??不能确定转移状态.考虑用优先队列储存最优决策点,可是发现当前选择最优不能保证最后最优,在后面可以将之前用过的替换过来. 比如数据: 3 5 4 6 只储存a[i]来决策不能延展到后面的状态,因 ...

  2. 【8.23校内测试】【贪心】【线段树优化DP】

    $m$的数据范围看起来非常有问题??仔细多列几个例子可以发现,在$m<=5$的时候,只要找到有两行状态按位$&$起来等于$0$,就是可行方案,如果没有就不行. #include<i ...

  3. 【8.30校内测试】【找规律模拟】【DP】【二分+贪心】

    对于和规律或者数学有关的题真的束手无策啊QAQ 首先发现两个性质: 1.不管中间怎么碰撞,所有蚂蚁的相对位置不会改变,即后面的蚂蚁不会超过前面的蚂蚁或者落后更后面的蚂蚁. 2.因为所有蚂蚁速度一样,不 ...

  4. 2018/8/15 qbxt 测试

    2018/8/15 qbxt 测试 期望得分:100:实际得分:50   不知道为什么写挂了,明明是个水题 T^T 思路:模拟 注意:如果用 char 类型存储的话,如果有'z' + 9 会爆char ...

  5. 【bzoj4869】[Shoi2017]相逢是问候 扩展欧拉定理+并查集+树状数组

    题目描述 Informatik verbindet dich und mich. 信息将你我连结. B君希望以维护一个长度为n的数组,这个数组的下标为从1到n的正整数.一共有m个操作,可以分为两种:0 ...

  6. POJ3376 Finding Palindromes —— 扩展KMP + Trie树

    题目链接:https://vjudge.net/problem/POJ-3376 Finding Palindromes Time Limit: 10000MS   Memory Limit: 262 ...

  7. 2019.7.9 校内测试 T3 15数码问题

    这一次是交流测试?边交流边测试(滑稽 15数码问题 大家应该都玩过这个15数码的游戏吧,就在桌面小具库那里面哦. 一看到这个题就知道要GG,本着能骗点分的原则输出了 t 个无解,本来以为要爆零,没想到 ...

  8. 2019.6.24 校内测试 NOIP模拟 Day 2 分析+题解

    看到Day 2的题真的想打死zay了,忒难了QwQ~ T1 江城唱晚 这明显是个求方案数的计数问题,一般的套路是DP和组合数学. 正如题目中所说,这个题是一个 math 题.      ----zay ...

  9. 2016.07.15——istringstream测试

    istringstream测试 1.istringstream strcin(str),字符串(str)可以包括多个单词,单词之间使用空格分开 #include "stdafx.h" ...

随机推荐

  1. 读书笔记 ~ Python黑帽子 黑客与渗透测试编程之道

    Python黑帽子  黑客与渗透测试编程之道   <<< 持续更新中>>> 第一章: 设置python 环境 1.python软件包管理工具安装 root@star ...

  2. c语言学习笔记.预处理.#ifndef

    #ifndef -> if not define 配合 #endif使用 在h头文件中使用,防止重复包含和编译. 也可以用条件编译来实现. 例如: 编写头文件 test.h 在头文件开头写上两行 ...

  3. perl6 一个猜测密码的注入

    use HTTP::UserAgent; my $ua = HTTP::UserAgent.new; my $r = HTTP::Request.new; my $c = HTTP::Cookies. ...

  4. Mysql储存过程8:repeat循环

    语法: repeat SQL until 条件 end repeat; 就是相当于其他语言中的: do{ # }while(); mysql> create procedure p1p() -& ...

  5. go标识符、变量、常量

    标识符 标识符是用来表示Go中的变量名或者函数名,以字母或_开头.后可跟着字母.数字. _ 关键字 关键字是Go语言预先定义好的,有特殊含义的标识符. 变量 1. 语法:var identifier ...

  6. React 16 源码瞎几把解读 【二】 react组件的解析过程

    一.一个真正的react组件编译后长啥样? 我们瞎几把解读了react 虚拟dom对象是怎么生成的,生成了一个什么样的解构.一个react组件不光由若干个这些嵌套的虚拟dom对象组成,还包括各种生命周 ...

  7. HDU 6195 2017沈阳网络赛 公式

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6195 题意:有M个格子,有K个物品.我们希望在格子与物品之间连数量尽可能少的边,使得——不论是选出M个 ...

  8. 设计模式--工厂模式 caffe_layer注册

    来源:http://www.cnblogs.com/zhouqiang/archive/2012/07/20/2601365.html 来源:http://blog.luoyetx.com/2016/ ...

  9. Android通过NTP服务器取得UTC标准时间

    1. http://hi-android.info/src/android/net/SntpClient.java.html 利用这个类调用NTP函数. 2. 通过函数client.requestTi ...

  10. AtCoder Non-decreasing(数学思维)

    题目链接:https://abc081.contest.atcoder.jp/tasks/arc086_b 题目大意:有n个数,最多可以执行2*n次操作,每次可以选择将ai加到aj上,最终使得该序列满 ...