2015 HNU warm up 05
来源:互联网 发布:下载知乎客户端 编辑:程序博客网 时间:2024/05/18 03:03
B.Circle of digits Input
给出一串数环(只包含数字‘1’~‘9’),把数环分成k部分,每个部分可以表达一个十进制数。令某种分割方法中,最大的数为该方法的特征值,求这个数环所能得到的最小特征值。
TLE,数据范围达到10^5。
令特征值最后可能得长度为len,那么len = (n + k - 1) % k;
能想的的做法是,扩展数环为两倍的数串,做一遍后缀数组,这样可以得到每个后缀的排名。利用height数组,得到每个位置往后扩展len长度之后的排名。之后令每个位置为最大值,贪心扫一遍(尽量使分块长度为len,否则为len-1,并检查剩下部分是否合法)。
但是还是会t。
据说做法是:
"先处理所有串,i 可能 的下一个串的起始位置i+len 和 i+len-1,i作为父亲,后面小于i的串两个做为儿子然后构造一个森林,然后用LCT维护,然后可以用枚举答案,答案做根,末串只有两种,access判断这两种末串根到根的节点总数是不是k,这样可以在O(logn)的时间内判断一个答案是否可行,n次O(nlogn),然后建树是也是(nlogn)。"
---- [hut]-Keam
不会。
暂且贴个t的。。
#include <algorithm>#include <iostream>#include <stdlib.h>#include <string.h>#include <stdio.h>using namespace std;#define MAXN 200010#define INF 123456789int sa[MAXN], sb[MAXN], r[MAXN];int wa[MAXN], wb[MAXN], wc[MAXN], wd[MAXN];int cmp(int *r, int a, int b, int l){ return r[a] == r[b] && r[a + l] == r[b + l];}void da(int *r, int *sa, int n, int m){ int *x = wa, *y = wb; for(int i = 0; i < m; i++) wd[i] = 0; for(int i = 0; i < n; i++) wd[x[i] = r[i]]++; for(int i = 1; i < m; i++) wd[i] += wd[i - 1]; for(int i = n - 1; i >= 0; i--) sa[--wd[x[i]]] = i; for(int j = 1, p = 0; p < n; j *= 2, m = p) { p = 0; for(int i = n - j; i < n; i++) y[p++] = i; for(int i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i] - j; for(int i = 0; i < n; i++) wc[i] = x[y[i]]; for(int i = 0; i < m; i++) wd[i] = 0; for(int i = 0; i < n; i++) wd[wc[i]]++; for(int i = 1; i < m; i++) wd[i] += wd[i - 1]; for(int i = n - 1; i >= 0; i--) sa[--wd[wc[i]]] = y[i]; swap(x, y), p = 1, x[sa[0]] = 0; for(int i = 1; i < n; i++) x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++; } return ;}int rank[MAXN], height[MAXN];void calheight(int n){ for(int i = 1; i <= n; i++) rank[sa[i]] = i; for(int i = 0, k = 0, j; i < n; i++) { if(k) k--; j = sa[rank[i] - 1]; while(r[i + k] == r[j + k]) k++; height[rank[i]] = k; }}bool flag;int n, k, h;int id[MAXN], rk[MAXN];inline bool cmp(int a, int b){ return rk[a] >= rk[b];}bool cmp(int a[], int b[]){ for(int i = 0; i < h; i++) { if(a[i] > b[i]) return true; if(a[i] < b[i]) return false; } return true;}bool ok1(int p){ for(int i = h; i <= n - h; i += h) if(!cmp(p, i + p)) return false; return true;}bool ok2(int p){ int re = n % k - 1; for(int i = h; re && (i <= n - h); i += h) { if(cmp(p, i + p)) re--; else i--; } if(re) return false; return true;}bool ok(int p){ if(flag) return ok2(p); else return ok1(p);}char str[MAXN];int main(){// freopen("B.in", "r", stdin); while(~scanf("%d%d%s", &n, &k, str)) { for(int i = 0; i < n; i++) r[i] = str[i] - '0'; for(int i = 0; i < n; i++) r[i + n] = r[i]; h = n / k + (n % k ? 1 : 0); flag = n % k ? true : false; int len = n + h; int tmp = r[len]; r[len] = 0; len++; da(r, sa, len, 12); calheight(len - 1); len--; r[len] = tmp; int cnt = 0; for(int i = 1; i <= len; i++) if(sa[i] <= len - h && height[i] < h) id[cnt++] = sa[i]; len = 2 * n; r[len] = 0; len++; da(r, sa, len, 12); calheight(len - 1); len--; int x = 0; for(int i = 1; i <= len; i++) { if(sa[i] <= len - h) { if(height[i] >= h) rk[sa[i]] = x; else rk[sa[i]] = ++x; } else rk[sa[i]] = INF; } int ans = id[cnt - 1]; for(int i = 0; i < cnt; i++) { //for(int j = 0; j < h; j++) printf("%d", r[j + id[i]]); cout << ' ' << rk[id[i]]; puts(""); if(ok(id[i])) { ans = id[i]; break; } } for(int j = 0; j < h; j++) printf("%d", r[j + ans]); puts(""); } return 0;}
0 0
- 2015 HNU warm up 05
- 2015 HNU Warm Up 01
- 2015 HNU warm up 02
- 2015 HNU warm up 03
- 2015 HNU Warm Up 04
- 2015 HNU Warm Up 06
- 2015 HNU warm up 07
- 2015 HNU warm up 12
- Bayan 2015 Contest Warm Up
- Bayan 2015 Contest Warm Up
- Bayan 2015 Contest Warm Up (D题)
- [Warm-up] Homework
- [Introduction and Warm-up]
- hdu 4612 Warm up
- HDU 4612 Warm up
- HDOJ 4612: Warm up
- hdu 4612 Warm up
- D - Warm up 2
- SDK配置环境变量
- 3ds max 样条线的几个常用操作
- Hadoop集群日常运维
- UIButton
- mybatis入门
- 2015 HNU warm up 05
- NSArray
- ACM822 计算机画图也挺有趣的哈!那我们就来用计算机画幅图吧。。。 输入 输入一个正整数N(0<N<=10),表示要输出的正方形的边上*的个数 输出 输出一个满足题意的正方形
- c++ STL pop_back() demo
- Python中set的用法
- Floyd算法
- iOS--封装好的json解析
- 【转】Python中的random模块
- setjmp和longjmp