[POI2008]KLO && POC
题意:给定一个序列 s1, s2,...sn,以及一个k,求一个连续的k个数,把s[i]...s[i+k-1]变成一个数s',使得sigma(|s[j]-s'|)(i<=j<=i+k-1)最小
思路:最近无聊切起poi。。顿感智商不够。。
这道题很容易想到把这些数变成中位数最优。。那么就可以用平衡树维护了。。
当然,直接用set维护也就够了。。不过为了练练代码。。我还是写了下splay。。
code:
/*
* Author: Yzcstc
* Created Time: 2014/11/8 19:03:57
* File Name: klo.cpp
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<stack>
#include<ctime>
#define repf(i, a, b) for (int i = (a); i <= (b); ++i)
#define M0(x) memset(x, 0, sizeof(x))
#define Inf 0x7fffffff
using namespace std;
const int maxn = ;
typedef long long ll;
int n, k;
int a[];
#define L ch[x][0]
#define R ch[x][1]
#define KT ch[ch[root][0]][1]
struct SplayTree{
int sz[maxn], pre[maxn], ch[maxn][], v[maxn];
ll sum[maxn];
int m, root;
void push_up(const int& x){
sz[x] = sz[L] + sz[R] + ;
sum[x] = sum[L] + sum[R] + v[x];
}
void init(){
M0(sz), M0(pre), M0(ch), M0(ch), M0(v);
}
void push_down(const int& x){
}
void rotate(int &x, const int f){
int y = pre[x], z = pre[y];
push_down(y), push_down(x);
ch[y][!f] = ch[x][f];
pre[ch[x][f]] = y;
pre[x] = pre[y];
if (z) ch[z][ch[z][] == y] = x;
ch[x][f] = y;
pre[y] = x;
push_up(y);
}
void splay(int &x, const int g){
push_down(x);
while (pre[x] != g){
int y = pre[x], z = pre[y];
if (z == g) rotate(x, ch[y][] == x);
else {
int f = (ch[z][] == y);
ch[y][!f] ? rotate(y, f) : rotate(x, !f);
rotate(x, f);
}
}
push_up(x);
if (!g) root = x;
}
void rto(int k,const int g, int& y){
int x = root;
while (sz[L] + != k){
push_down(x);
if (sz[L] >= k) x = L;
else {
k -= sz[L] + ;
x = R;
}
}
y = x;
splay(x, g);
}
int search(int x, int val){
int y = -;
while (x){
y = x;
if (val <= v[x]) y = x, x = L;
else y = x, x = R;
}
return y;
}
void insert(int x, int val){
int y = search(root, val);
ch[y][val > v[y]] = x;
pre[x] = y;
while (y) push_up(y), y = pre[y];
splay(x, );
}
int findpre(int x){
x = L;
while (R) x = R;
return x;
}
void split(int x){
splay(x, );
int lt = findpre(x);
if (lt){
splay(lt, x);
root = lt, pre[root] = ;
ch[root][] = R;
if (R) pre[R] = root;
} else root = R, pre[R] = ;
push_up(root);
L = R = ;
}
ll query(const int& n, int &vv){
int k = (n+) / , x;
if (!(n & )) ++k;
rto(k, , x);
ll res = (ll)v[x] * (k-) - sum[ch[root][]] + sum[ch[root][]] - (ll)v[x] * (n-k);
vv = v[x];
return res;
}
} S; void init(){
for (int i = ; i <= n; ++i)
scanf("%d", &a[i]);
} void solve(){
if (k == ){
puts("");
for (int i = ; i <= n; ++i)
printf("%d\n", a[i]);
return;
}
S.root = , S.sz[] = , S.sum[] = S.v[] = a[];
for (int i = ; i <= n; ++i)
S.sz[i] = , S.v[i] = S.sum[i] = a[i];
for (int i = ; i <= k; ++i)
S.insert(i, a[i]);
int ans_pos = , ans_val = , val;
ll ans = S.query(k, ans_val), tmp;
for (int i = k + ; i <= n; ++i){
S.split(i-k);
S.insert(i, a[i]);
tmp = S.query(k, val);
if (tmp < ans)
ans = tmp, ans_val = val, ans_pos = i - k + ;
}
cout << ans << endl;
for (int i = ans_pos; i <= ans_pos+k-; ++i) a[i] = ans_val;
for (int i = ; i <= n; ++i) printf("%d\n", a[i]);
} int main(){
// freopen("a.in", "r", stdin);
// freopen("a.out", "w", stdout);
while (scanf("%d%d", &n, &k) != EOF){
init();
solve();
}
return ;
}
题意:有 n(n<=1000)个串,每个串的程度都<=100,有 m 次操作,每次操作都是将第 p1个串的第 w1 个字母和第 p2 个串的第 w2 个字母交换,问对于每一个串 i,在这些操作执行的过程中,它最多几个串相同过。
思路:由于每个串只有100,我们可以用n*m的时间进行hash。。
那么剩下来就是直接维护hash值为某一个数的集合了。。。平衡树可维护。。
code:
/*
* Author: Yzcstc
* Created Time: 2014/11/8 13:53:39
* File Name: poc.cpp
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<stack>
#include<ctime>
#define M0(x) memset(x, 0, sizeof(x))
#define Inf 0x7fffffff
using namespace std;
#define M 10003
const int maxn = ;
/*** splay-tree***/
#define L ch[x][0]
#define R ch[x][1]
int sz[maxn], pre[maxn], rt[maxn], ms[maxn], ch[maxn][], lz[maxn]; void Splay_init(){
M0(sz), M0(pre), M0(rt), M0(ms), M0(ch), M0(lz);
} void pushdown(const int &x){
if (lz[x]){
if (L) lz[L] = max(lz[L], lz[x]), ms[L] = max(ms[L], lz[x]);
if (R) lz[R] = max(lz[R], lz[x]), ms[R] = max(ms[R], lz[x]);
lz[x] = ;
}
} void pushup(int x){} void rotate(int &x, const int f){
int y = pre[x], z = pre[y];
pushdown(y), pushdown(x);
ch[y][!f] = ch[x][f];
pre[ch[x][f]] = y;
pre[x] = pre[y];
if (z) ch[z][ch[z][] == y] = x;
ch[x][f] = y;
pre[y] = x;
pushup(y);
} void splay(int &x, const int g, int &root){
pushdown(x);
while (pre[x] != g){
int y = pre[x], z = pre[y];
if (z == g) rotate(x, ch[y][] == x);
else {
int f = (ch[z][] == y);
ch[y][!f] ? rotate(y, f) : rotate(x, !f);
rotate(x, f);
}
}
pushup(x);
if (!g) root = x;
} void update(int &root, int s){
lz[root] = max(lz[root], s);
ms[root] = max(ms[root], s);
} int right(int x){
while (R) x = R;
return x;
} void insert(int& root, int x, int size){
int p = right(root);
splay(p, , root);
ch[p][] = x, pre[x] = p;
update(root, size);
} void split(int& root, int x){
splay(x, , root);
int lt = ch[x][];
lt = right(lt);
if (lt){
splay(lt, x, root), root = lt;
if (R) pre[R] = root;
pre[root] = , ch[root][] = R;
} else
root = R, pre[R] = ;
L = R = ;
} /*** splay-end***/
map<int, int> mp;
char s[][];
int hs[], n, m, q, pw[]; inline int Hash(const char s[]){
int res = ;
for (int i = ; i < m; ++i)
res = res * M + s[i];
return res;
} void init(){
pw[m-] = ;
for (int i = m-; i >= ; --i)
pw[i] = pw[i+] * M;
for (int i = ; i <= n; ++i){
scanf("%s", s[i]);
hs[i] = Hash(s[i]);
}
} int f[maxn];
void solve(){
Splay_init();
mp.clear();
int tot = , u, v;
for (int i = ; i <= n; ++i){
u = hs[i], v = mp[u];
if (v)
insert(rt[v], i, ++sz[v]);
else {
v = mp[u] = ++tot;
sz[v] = ; rt[v] = i;
update(rt[v], );
}
}
int a, x1, b, x2;
int h1, h2;
while (q--){
scanf("%d%d%d%d", &a, &x1, &b, &x2);
x1--, x2--;
if (a == b){
h1 = hs[a] + pw[x1] * (s[b][x2] - s[a][x1]) + pw[x2] * (s[a][x1] - s[b][x2]);
u = mp[hs[a]], split(rt[u], a);
if (--sz[u] == ) mp[hs[a]] = rt[u] = ;
v = mp[h1];
if (v)
insert(rt[v], a, ++sz[v]);
else {
v = mp[h1] = ++tot;
sz[v] = ; rt[v] = a;
update(rt[v], );
}
hs[a] = h1;
swap(s[a][x1], s[b][x2]);
continue;
}
h1 = hs[a] + pw[x1] * (s[b][x2] - s[a][x1]);
h2 = hs[b] + pw[x2] * (s[a][x1] - s[b][x2]);
u = mp[hs[a]], split(rt[u], a);
if (--sz[u] == ) mp[hs[a]] = rt[u] = ;
u = mp[hs[b]], split(rt[u], b);
if (--sz[u] == ) mp[hs[b]]= rt[u] = ;
v = mp[h1];
if (v)
insert(rt[v], a, ++sz[v]);
else {
v = mp[h1] = ++tot;
sz[v] = ; rt[v] = a;
update(rt[v], );
}
v = mp[h2];
if (v)
insert(rt[v], b, ++sz[v]);
else {
v = mp[h2] = ++tot;
sz[v] = ; rt[v] = b;
update(rt[v], );
}
hs[a] = h1, hs[b] = h2;
swap(s[a][x1], s[b][x2]);
}
for (int i = ; i <= n; ++i){
u = mp[hs[i]];
splay(i, , rt[u]);
f[i] = ms[i];
}
for (int i = ; i <= n; ++i)
printf("%d\n", f[i]);
} int main(){
// freopen("a.in", "r", stdin);
// freopen("a.out", "w", stdout);
while (scanf("%d%d%d", &n, &m, &q) != EOF){
init();
solve();
}
fclose(stdin); fclose(stdout);
return ;
}
[POI2008]KLO && POC的更多相关文章
- 【BZOJ1125】【POI2008】poc - splay+哈希
题意: Description n列火车,每条有l节车厢.每节车厢有一种颜色(用小写字母表示).有m次车厢交换操作.求:对于每列火车,在交换车厢的某个时刻,与其颜色完全相同的火车最多有多少. Inpu ...
- [BZOJ1112][POI2008]砖块Klo
[BZOJ1112][POI2008]砖块Klo 试题描述 N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另 ...
- BZOJ 1112: [POI2008]砖块Klo
1112: [POI2008]砖块Klo Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1736 Solved: 606[Submit][Statu ...
- 1112: [POI2008]砖块Klo
1112: [POI2008]砖块Klo Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1245 Solved: 426[Submit][Statu ...
- 【BZOJ1112】[POI2008]砖块Klo Treap
[BZOJ1112][POI2008]砖块Klo Description N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出 ...
- 【BZOJ1125】[POI2008]Poc hash+map+SBT
[BZOJ1125][POI2008]Poc Description n列火车,每条有l节车厢.每节车厢有一种颜色(用小写字母表示).有m次车厢交换操作.求:对于每列火车,在交换车厢的某个时刻,与其颜 ...
- [Bzoj1112][POI2008]砖块Klo(splay)
1112: [POI2008]砖块Klo Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2353 Solved: 831[Submit][Statu ...
- [BZOJ 1112] [POI2008] 砖块Klo 【区间K大】
题目链接:BZOJ - 1112 题目分析 枚举每一个长度为k的连续区间,求出这个区间的最优答案,更新全局答案. 可以发现,这个区间的所有柱子最终都变成这k个数的中位数时最优,那么我们就需要查询这个区 ...
- [BZOJ1112] [POI2008] 砖块Klo (treap)
Description N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另一柱.仓库无限大. 现在希望用最小次 ...
随机推荐
- 安卓app中嵌入一个H5页面,当手机系统设置字体变大时,如何使H5页面的字体不会随用户自己调整的系统字体变化而变化?
webview.getSettings().setTextZoom(100);WebView加上这个设置后,WebView里的字体就不会随系统字体大小设置发生变化了. https://segmentf ...
- Python模块:hashlib
hashlib:提供了常见的摘要算法,如MD5,SHA1等. import hashlib m = hashlib.md5() m.update('how to use md5 in python h ...
- php单独编译扩展模块
以pdo_mysql为例: 1.下载 文件 或者 进入 在PHP源码包中进入ext/pdo_mysql http://pecl.php.net/get/PDO_MYSQL-1.0.2.tgz 2.解压 ...
- JavaScript基础知识整理(2)
15.处理图像 注意:(1)在写js文件时,尽量将函数的声明往后写,将函数调用写在前面,这样能够使代码结构很清晰. (2)一个网页中翻转器一般超过3个,所以使用for循环减少重复使用翻转器代码的次数. ...
- OpenSource.organization-in-github
1. gosquared https://github.com/gosquared 2. slack https://github.com/slackhq 3. The New York Times ...
- [NOIP2015]信息传递
[NOIP2015]信息传递[问题描述]有
- POJ 3281 Dining 最大流
饮料->牛->食物. 牛拆成两点. //#pragma comment(linker, "/STACK:1024000000,1024000000") #include ...
- 在github上搭建博客的问题
最近想到要建立一个自己的博客,以便记录自己在学习中遇到的问题.发现github免费提供空间,正好可以利用它来搭建自己的博客.毕竟github pages免费空间,不限制流量,每次的博客改动和博客模板的 ...
- sprintf()函数,把数字转换成字符串
char str_2[10]; int a=1234321; sprintf(str_2,"%d",a);
- Python多线程开发简介
Python的并发程序可以使用multiprocessing库.threading库.asyncio库.concurrent.futures库以及selectors库等等协助编写: multiproc ...