UOJ Round #15 [构造 | 计数 | 异或哈希 kmp]
UOJ Round #15
大部分题目没有AC,我只是水一下部分分的题解...
225【UR #15】奥林匹克五子棋
题意:在n*m的棋盘上构造k子棋的平局
题解:
玩一下发现k=1, k=2无解,然后间隔着,上下两行相同:
010101
010101
101010
101010
这样构造下来就行了。
然后要特判n=1 或 m=1,这时候k=2可以有解
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N = 505;
inline int read() {
char c=getchar(); int x=0,f=1;
while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
return x*f;
}
int n, m, k, a[N][N], t[N][N];
void paint(int *a, int f) {for(int j=1; j<=m; j++) a[j] = (j&1) ^ f;}
inline void _walk(int &x, int &y) {
y++;
if(y == m+1) x++, y=1;
}
void walk(int &x, int &y, int f) {
while(a[x][y] != f) _walk(x, y);
}
void solve1() {
if(k == 1) {puts("-1"); return;}
if(n == 1) for(int i=1; i<=m; i++) printf("%d %d\n", 1, i);
else for(int i=1; i<=n; i++) printf("%d %d\n", i, 1);
}
int main() {
freopen("in", "r", stdin);
//freopen("out", "w", stdout);
n = read(); m = read(); k = read();
if(min(n, m) == 1) {solve1(); return 0;}
if(k == 1 || k == 2) {puts("-1"); return 0;}
int flag = 0;
if((m&1) && (~n&1)) swap(n, m), flag = 1;
int lim = (n>>1) + 1;
for(int i=1; i <= lim; i++) paint(a[(i<<1)-1], i&1), paint(a[i<<1], i&1);
if(flag) {
for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) t[j][i] = a[i][j];
swap(n, m);
for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) a[i][j] = t[i][j];
}
int b = 0, w = 0;
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++) {
if(a[i][j] == 1) b++;
else w++;
}
if(b < w) b = 0, w = 1; else b = 1, w = 0;
int bx = 1, by = 1, wx = 1, wy = 1;
lim = n * m;
for(int i=1; i <= lim; i++) {
if(i & 1) walk(bx, by, b), printf("%d %d\n", bx, by), _walk(bx, by);
else walk(wx, wy, w), printf("%d %d\n", wx, wy), _walk(wx, wy);
}
//puts("\ntest");
//for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) printf("%d%c", a[i][j], j==m ? '\n' : ' ');
}
226【UR #15】奥林匹克环城马拉松
- 题意:有向 树 / 环 / 基环树 的欧拉回路计数
- 题解:题解太神了看不懂啊,我只能看懂树的...
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
typedef long long ll;
const int N = 1e5+5, P = 998244353;
inline int read() {
char c=getchar(); int x=0,f=1;
while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
return x*f;
}
int n, m, u, v, w, de[N], t[N];
struct edge {int v, ne;} e[N<<1];
int cnt, h[N];
inline void ins(int u, int v, int w) {
e[++cnt] = (edge) {v, h[u]}; h[u] = cnt;
e[++cnt] = (edge) {u, h[v]}; h[v] = cnt;
}
ll inv[N*10], fac[N*10], facInv[N*10];
inline ll C(int n, int m) {return fac[n] * facInv[m] %P * facInv[n-m] %P;}
int main() {
freopen("in", "r", stdin);
n = read(); m = read();
int flag = 1, lim = 0;
for(int i=1; i<=m; i++) {
u = read(), v = read(), w = t[i] = read(), de[u] += w, de[v] += w;
lim = max(lim, w);
if(w & 1) flag = 0;
}
for(int i=1; i<=n; i++) {
if(de[i] & 1) {puts("0"); return 0;}
de[i] >>= 1;
lim = max(lim, de[i]);
}
inv[1] = fac[0] = facInv[0] = 1;
for(int i=1; i <= lim; i++) {
if(i != 1) inv[i] = (P - P/i) * inv[P%i] %P;
fac[i] = fac[i-1] * i %P;
facInv[i] = facInv[i-1] * inv[i] %P;
}
if(m == n-1) {
if(!flag) {puts("0"); return 0;}
ll ans = 1;
for(int i=1; i<=n; i++) ans = ans * fac[de[i] - 1] %P; //printf("ans %lld\n", ans);
for(int i=1; i<=m; i++) ans = ans * C(t[i], t[i] >> 1) %P * (t[i] >> 1) %P;
printf("%lld\n", ans);
}
}
227【UR #15】奥林匹克数据结构
题意:长为n的序列a,Q次询问,给出一个长m的序列b,求a有多少长m的子序列和b的相对大小关系相同
题解:
太神了不会写啊,看了题解之后写了一下午一晚上才有50部分分
一开始想的是把a的子序列离散化然后和b判断相等
这样对于\(m_i \le 25\)的点可以哈希一下,预处理\(O(nm^2)\),结果T了
发现题解里的这些点的预处理是\(O(nm\log n)\)的!
想了一下,发现不需要离散化,可以定义每个点的名次为前面比它小的个数+1,照样可行!
然后用树状数组+异或哈希就可以拿这20分啦
试着写了一下AC自动机+主席树的离线做法,还是有细节不会处理啊,又去写了kmp的做法。
其实就是匹配b的名次序列在a中出现次数,只不过a中元素的名次依赖于序列的起始位置。
kmp的border是单调递减的,所以用bit维护当前的border,移动now时暴力修改,求名次用bit求
好喵啊!
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <ctime>
double tim() {return (double) clock() / CLOCKS_PER_SEC;}
using namespace std;
typedef long long ll;
const int N = 1e5+5;
inline int read() {
char c=getchar(); int x=0,f=1;
while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
return x*f;
} int type, n, Q, a[N], b[N * 5]; void decode(int *b, int m, int ans) {
static int c[N];
for(int i=1; i<=m; i++) c[(i+ans-1) % m + 1] = b[i];
for(int i=1; i<=m; i++) b[i] = c[i];
} namespace bit {
int c[N], t[N], T;
inline void add(int p, int v) {
for(; p <= n; p += p&-p) {
if(t[p] != T) t[p] = T, c[p] = v;
else c[p] += v;
}
}
inline int sum(int p) {
int ans = 0;
for(; p; p -= p&-p)
if(t[p] == T) ans += c[p];
return ans;
}
} namespace m_25 {
int s[26][N];
int h[N]; using bit::add; using bit::sum; void ini_hash() {
srand(317);
for(int i=1; i<=25; i++) h[i] = rand() << 15 ^ rand(); for(int i=1; i<=n; i++) {
int ans = 0; bit::T++;
for(int m = 1; m <= 25 && i+m-1 <= n; m++)
ans = ans << 1 ^ h[sum(a[i+m-1])], s[m][++s[m][0]] = ans, add(a[i+m-1], 1);
}
for(int m = 1; m <= 25; m++) sort(s[m] + 1, s[m] + s[m][0] + 1);
}
int get_hash(int *b, int m) {
int ans = 0; bit::T++;
for(int i=1; i<=m; i++) ans = ans << 1 ^ h[sum(b[i])], add(b[i], 1);
return ans;
}
int Count(int *a, int x) {
return upper_bound(a + 1, a + a[0] + 1, x) - lower_bound(a + 1, a + a[0] + 1, x);
}
int ans;
void solve() {
ini_hash();
for(int i=1; i<=Q; i++) {
int m = read();
for(int i=1; i<=m; i++) b[i] = read();
if(type) decode(b, m, ans);
int x = get_hash(b, m);
ans = Count(s[m], x);
printf("%d\n", ans);
}
}
} namespace kmp {
int fail[N], rnk[N], _a[N];
void build(int *s, int n) {
bit::T++;
for(int i=1; i<=n; i++) rnk[i] = bit::sum(s[i]) + 1, bit::add(s[i], 1);
bit::T++;
fail[1] = 0;
for(int i=2; i<=n; i++) {
int now = fail[i-1];
//printf("iiii %d %d\n", i, now);
while(now && bit::sum(s[i]) + 1 != rnk[now+1]) {
for(int j = i-now; j <= i-fail[now]-1; j++) bit::add(s[j], -1);
now = fail[now];
}
if(rnk[now+1] == bit::sum(s[i]) + 1) fail[i] = now+1, bit::add(s[i], 1);
else fail[i] = 0;
}
//for(int i=1; i<=n; i++) printf("%d ", rnk[i]); puts(" rnk");
//for(int i=1; i<=n; i++) printf("%d ", fail[i]); puts(" fail");
} void walk(int *a, int n, int *b, int m) {
bit::T++;
int now = 0, ans = 0;
for(int i=1; i<=n; i++) { //printf("-----i %d %d\n", i, now);
while(now && bit::sum(a[i]) + 1 != rnk[now+1]) {
//printf("lose [%d, %d]\n", i-now, i-fail[now]-1);
for(int j = i-now; j <= i-fail[now]-1; j++) bit::add(a[j], -1);
now = fail[now];
}
if(bit::sum(a[i]) + 1 == rnk[now+1]) now++, bit::add(a[i], 1);
if(now == m) ans++;
}
printf("%d\n", ans);
}
} namespace type_0 {
void solve() {
for(int i=1; i<=Q; i++) {
int m = read();
for(int j=1; j<=m; j++) b[j] = read();
kmp::build(b, m);
kmp::walk(a, n, b, m);
for(int i=1; i<=m; i++) kmp::fail[i] = kmp::rnk[i] = 0;
}
}
} int main() {
freopen("in", "r", stdin);
freopen("out", "w", stdout);
type = read();
n = read(); Q = read();
for(int i=1; i<=n; i++) a[i] = read();
if(type == 0) type_0::solve();
else m_25::solve();
return 0;
}下面这个不会写的代码只是留作纪念
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <ctime>
double tim() {return (double) clock() / CLOCKS_PER_SEC;}
using namespace std;
typedef long long ll;
const int N = 1e5+5;
inline int read() {
char c=getchar(); int x=0,f=1;
while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
return x*f;
} int type, n, Q, a[N], b[N * 5]; void decode(int *b, int m, int ans) {
static int c[N];
for(int i=1; i<=m; i++) c[(i+ans-1) % m + 1] = b[i];
for(int i=1; i<=m; i++) b[i] = c[i];
} namespace bit {
int c[N], t[N], T;
inline void add(int p, int v) {
for(; p <= n; p += p&-p) {
if(t[p] != T) t[p] = T, c[p] = v;
else c[p] += v;
}
}
inline int sum(int p) {
int ans = 0;
for(; p; p -= p&-p)
if(t[p] == T) ans += c[p];
return ans;
}
} namespace m_25 {
int s[26][N];
int h[N]; using bit::add; using bit::sum; void ini_hash() {
srand(317);
for(int i=1; i<=25; i++) h[i] = rand() << 15 ^ rand(); for(int i=1; i<=n; i++) {
int ans = 0; bit::T++;
for(int m = 1; m <= 25 && i+m-1 <= n; m++)
ans = ans << 1 ^ h[sum(a[i+m-1])], s[m][++s[m][0]] = ans, add(a[i+m-1], 1);
}
for(int m = 1; m <= 25; m++) sort(s[m] + 1, s[m] + s[m][0] + 1);
}
int get_hash(int *b, int m) {
int ans = 0; bit::T++;
for(int i=1; i<=m; i++) ans = ans << 1 ^ h[sum(b[i])], add(b[i], 1);
return ans;
}
int Count(int *a, int x) {
return upper_bound(a + 1, a + a[0] + 1, x) - lower_bound(a + 1, a + a[0] + 1, x);
}
int ans;
void solve() {
ini_hash();
for(int i=1; i<=Q; i++) {
int m = read();
for(int i=1; i<=m; i++) b[i] = read();
if(type) decode(b, m, ans);
int x = get_hash(b, m);
ans = Count(s[m], x);
printf("%d\n", ans);
}
}
} namespace tr {
#define lc(x) t[x].l
#define rc(x) t[x].r
struct meow {int l, r, size;} t[N];
int sz, root[N];
void insert(int &x, int l, int r, int p) {
t[++sz] = t[x]; x = sz;
t[x].size ++;
if(l == r) return;
int mid = (l+r) >> 1;
if(p <= mid) insert(lc(x), l, mid, p);
else insert(rc(x), mid+1, r, p);
}
int sum(int x, int y, int l, int r, int ql, int qr) {
//if(ql > qr) return 0;
if(ql <= l && r <= qr) return t[y].size - t[x].size;
else {
int mid = (l+r) >> 1, ans = 0;
if(ql <= mid) ans += sum(lc(x), lc(y), l, mid, ql, qr);
if(mid < qr) ans += sum(rc(x), rc(y), mid+1, r, ql, qr);
return ans;
}
}
}
using tr::root;
inline int rank(int x, int l, int r) {return tr::sum(root[l-1], root[r], 1, n, 1, a[x]);} namespace ac {
#define fir first
#define sec second
int pos[N];
struct meow {
map<int, int> ch;
map<int, int> mp;
int fail, cnt, rnk;
int count(int c) {return ch.count(c);}
int has(int x) {return mp.count(x);}
} t[N * 5];
map<int, int>::iterator it;
int sz, deep[N];
void insert(int *s, int m, int id) { printf("\ninsert %d\n", id);
int u = 0;
bit::T++;
for(int i=1; i<=m; i++) {
int c = s[i];
if(!t[u].ch[c]) {
t[u].ch[c] = ++sz;
deep[sz] = deep[u] + 1;
t[sz].rnk = bit::sum(s[i]) + 1;
t[u].mp[t[sz].rnk] = sz;
}
bit::add(s[i], 1);
u = t[u].ch[c];
printf("u %d %d %d\n", u, deep[u], t[u].rnk);
}
pos[id] = u;
}
void build() {
static int q[N], head = 1, tail = 1;
for(it = t[0].ch.begin(); it != t[0].ch.end(); it++) q[tail++] = it -> sec;
while(head != tail) {
int u = q[head++];
for(it = t[u].ch.begin(); it != t[u].ch.end(); it++) {
int v = it -> sec, rnk = t[v].rnk, now = t[u].fail;
while(now && !t[now].has(rnk)) now = t[now].fail;
if(t[now].has(rnk)) t[v].fail = t[now].mp[rnk];
q[tail++] = v;
}
}
} void walk(int *a, int n) { puts("\nwalk");
int u = 0;
for(int i=1; i<=n; i++) {
int l = i - deep[u], r = i, rnk = rank(i, l, r);
while(u && !t[u].has(rnk)) u = t[u].fail;
if(t[u].has(rnk)) u = t[u].mp[rnk];
t[u].cnt ++; printf("u %d\n", u);
}
} int f[N * 5];
void dfs(int u) { //printf("dfs %d\n", u);
f[u] = t[u].cnt;
for(map<int, int>::iterator it = t[u].ch.begin(); it != t[u].ch.end(); it++)
dfs(it -> sec), f[u] += f[it -> sec];
}
} namespace type_0 {
void solve() {
for(int i=1; i<=n; i++) root[i] = root[i-1], tr::insert(root[i], 1, n, a[i]);
//puts("rank");
//for(int l=1; l<=n; l++) for(int r=l; r<=n; r++) printf("rank [%d, %d] %d\n", l, r, rank(r, l, r));
for(int i=1; i<=Q; i++) {
int m = read();
for(int j=1; j<=m; j++) b[j] = read();
ac::insert(b, m, i);
}
ac::build();
ac::walk(a, n);
ac::dfs(0); //puts("hi");
using ac::f; using ac::pos;
for(int i=1; i<=Q; i++) printf("%d\n", f[pos[i]]);
}
} int main() {
freopen("in", "r", stdin);
//freopen("out", "w", stdout);
type = read();
n = read(); Q = read();
for(int i=1; i<=n; i++) a[i] = read();
if(type == 0) type_0::solve();
else m_25::solve();
return 0;
}
UOJ Round #15 [构造 | 计数 | 异或哈希 kmp]的更多相关文章
- 【UOJ Round #5】
构造+贪心/数论 为什么只有两个标题呢……因为第二题我不会…… 怎样提高智商 构造题……然而一开始半天我都yy不出来…… 后来我想:这题应该不会特别麻烦,而且既然样例只给了1,可能再给大一点就让人发现 ...
- UOJ Round #1 [数论 | DP 排列]
UOJ Round #1 难度很良心啊! 做出了前两题,第三题看到仙人掌就吓哭了. [UR #1]缩进优化 就是求 \[ \sum_{i=1}^n a_i - (x-1)\sum_{i=1}^n\lf ...
- 【UOJ Round #1】
枚举/DP+排列组合 缩进优化 QAQ我当时一直在想:$min\{ \sum_{i=1}^n (\lfloor\frac{a[i]}{x}\rfloor + a[i] \ mod\ x) \}$ 然而 ...
- 【UOJ Round #8】
A 一道不错的题,虽然大家都觉得是水题,然而蒟蒻我想出来的好慢……Orz alpq 发现其实就是一个网格图,每一个大块都是同一颜色……横纵坐标互不干扰…… //UOJ Round #8 A #incl ...
- BestCoder Round#15 1001-Love
http://acm.hdu.edu.cn/showproblem.php?pid=5082 Love Time Limit: 2000/1000 MS (Java/Others) Memory ...
- HYNB Round 15: PKU Campus 2019
HYNB Round 15: PKU Campus 2019 C. Parade 题意 将平面上n*2个点安排在长度为n的两行上. 做法 首先可以忽略每个点之间的影响,只用考虑匹配即可 然后把所以点归 ...
- swift 学习- 15 -- 构造过程 01
// 构造过程 是使用类,结构体 或 枚举类型的实例之前的准备过程, // 在新实例可用前必须执行这个过程, 具体操作包括 设置实例中每个存储型属性的初始值 和 执行其他必须的设置 或 初始化工作 / ...
- CodeForces - 862C Mahmoud and Ehab and the xor(构造)【异或】
<题目链接> 题目大意: 给出n.m,现在需要你输出任意n个不相同的数(n,m<1e5),使他们的异或结果为m,如果不存在n个不相同的数异或结果为m,则输出"NO" ...
- CodeForces.1174D.EhabandtheExpectedXORProblem(构造前缀异或和数组)
题目链接 这道题比赛的时候没做出来,赛后补题的时候发现其实可以构造一个前缀异或和数组,然后根据初始化的第一个值进行填数,但是作为菜鸡的我虽然坚信自己的想法是正确的却想了很久也没有能够构造出来所谓的前缀 ...
随机推荐
- 最短路 spfa 算法 && 链式前向星存图
推荐博客 https://i.cnblogs.com/EditPosts.aspx?opt=1 http://blog.csdn.net/mcdonnell_douglas/article/deta ...
- 跟我一起读postgresql源码(十二)——Executor(查询执行模块之——Materialization节点(下))
接前文,我们继续说剩下的4个Materialization节点. 7.SetOp节点 SetOp节点用于处理集合操作,对应于SQL语句中的EXCEPT.INTERSECT两种集合操作,至于另一种集合操 ...
- c语言基础学习01
=============================================================================每一种语言都有其独特的语法规则与语言定义. 指 ...
- 分布式计算框架学习笔记--hadoop工作原理
(hadoop安装方法:http://blog.csdn.net/wangjia55/article/details/53160679这里不再累述) hadoop是针对大数据设计的一个计算架构.如果你 ...
- RPM挂载光盘(使用iso里面的来搭建yum环境)就是离线模式,
找到光盘的完整路径名.在命令行输入:ls -l /dev | grep cdrom. 可以看到光盘的名字叫做:cdrom1.然后在命令行执行: mount /dev/cdrom1 /mnt/ ...
- SSL数字证书Nginx配置部署
由于小程序和Ios端的需要,公司的项目需要从原来的http协议扩展到https协议,因为项目本来就有采用nginx做了负载均衡,但是之前配置nginx的时候并没有配置关于https的内容,所以需要做这 ...
- Win10下安装RabbitMQ以及基本知识学习
一.为什么选择RabbitMQ? 先说一下场景,这是我们公司遇到,当然我这里不做业务评价哈?虽然我知道他很不合理,但是我是无能为力的.APP端部分注册是Java开发的系统,然后业务端是C#开 ...
- cesium编程入门(四)界面介绍及小控件隐藏
感性认识 界面介绍,viewer Geocoder : 查找位置工具,查找到之后会将镜头对准找到的地址,默认使用bing地图 Home Button :视角返回初始位置. Scene Mode Pic ...
- MLlib--决策树
转载请标明出处http://www.cnblogs.com/haozhengfei/p/d65ab6ccff684db729f44a947ac9e7da.html 决策树 1.什么是决策树 决策 ...
- 从零开始学习前端JAVASCRIPT — 4、JavaScript基础Math和Date对象的介绍
Math对象的介绍 1:Math对象 Math 对象用于执行数学任务.并不像 Date 和 String 那样是对象的类,因此没有构造函数 Math().您无需创建它,通过把 Math 作为对象使用就 ...