之前都没做出来的同名题简直留下心理阴影啊...其实这道题还是挺好想的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. [\u4e00-\u9fa5] //匹配中文字符

     [\u4e00-\u9fa5] //匹配中文字符 ^[1-9]\d*$    //匹配正整数^[A-Za-z]+$   //匹配由26个英文字母组成的字符串^[A-Z]+$      //匹配由26 ...

  2. 使用Sass预定义一些常用的样式,非常方便

    CSS预处理技术现在已经非常成熟,比较流行的有Less,Sass,Stylus,在开发过程中提升我们的工作效率,缩短开发时间,方便管理和维护代码,可以根据自己的喜好选择一款自己喜欢的工具开发,使用很接 ...

  3. Mysql储存过程3:if语句

    --if/else语句 if 条件 then SQL语句 else SQL语句elseifSQL语句 end if; create procedure test1( number int ) begi ...

  4. python之微信公众号开发(基本配置和校验)

    前言 最近有微信公众号开发的业务,以前没有用python做过微信公众号开发,记录一下自己的学习和开发历程,共勉! 公众号类型 订阅号 普通订阅号 认证订阅号 服务号 普通服务号 认证服务号 服务方式 ...

  5. 用C#实现对MSSqlServer数据库的增删改查---Server层(WaterLevelSetServer.cs、DeviceSetServer.cs)

    在Server层定义WaterLevelSetServer和WaterLevelRecordServer两个子类,分别继承DeviceSetServer和DeviceRecordServer. usi ...

  6. ProxySQL(MGR)部署故障:'sys.gr_member_routing_candidate_status' doesn't exist

    ProxySQL(MGR) 故障排查: 故障现象:runtime_mysql_servers节点状态offline_hostgroup(本案例为15) 日志关键信息: [WARNING] Group ...

  7. python魔法函数__dict__和__getattr__的妙用

    python魔法函数__dict__和__getattr__的妙用 __dict__ __dict__是用来存储对象属性的一个字典,其键为属性名,值为属性的值. 既然__dict__是个字典那么我们就 ...

  8. 以太坊go-ethereum客户端(三)两种全节点启动模式

    这篇博客介绍一下go-ethereum全节点的两种启动模式:主网络快速启动和测试网络快速启动.这也是客户端所提供的两种启动方式,直接拿来使用即可.下面具体介绍一下使用方法. 主网络快速启动 其实,我们 ...

  9. python基础(11)--面向对象

    1.概述 面向过程:根据业务的逻辑从上到下写代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发更快更好更强 面向过程编程最易被初学者接受 ...

  10. 最直白、最易懂的话带你认识和学会---数据分析基础包之numpy的使用

    前言 numpy是一个很基础很底层的模块,其重要性不言而喻,可以说对于新手来说是最基础的入门必须要学习的其中之一.在很多数据分析,深度学习,机器学习亦或是人工智能领域的模块中,很多的底层都会用到这个模 ...