[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:从仓库中拿出一块砖,放到另一柱.仓库无限大. 现在希望用最小次 ...
随机推荐
- Python SQLAlchemy --3
本文為 Python SQLAlchemy ORM 一系列教學文: 刪除 學會如何查詢之後,就能夠進行後續的刪除.更新等操作. 同樣地,以幾個範例做為學習的捷徑. 123456789 user_1 = ...
- web页面全角&半角
根据Unicode编码,全角空格为12288,半角空格为32 : 其他字符半角(33-126)与全角(65281-65374)的对应关系是:均相差65248 全角-->半角函数 //半角转换 ...
- Coursera Machine Learning : Regression 多元回归
多元回归 回顾一下简单线性回归:一个特征,两个相关系数 实际的应用要比这种情况复杂的多,比如 1.房价和房屋面积并不只是简单的线性关系. 2.影响房价的因素有很多,不仅仅是房屋面积,还包括很多其他因素 ...
- [转] Oracle analyze table 使用总结
转自:http://www.cnblogs.com/einyboy/archive/2012/08/09/2630321.html analyze table 一般可以指定分析: 表,所有字段,所有索 ...
- 大批量GPS坐标转百度坐标
一. 百度地图API大批量转换时有数量限制,一个一个转. 用到的方法接口 /** 源坐标 格式:经度,纬度;经度,纬度… 最多支持100个; 源坐标类型:默认为1,即GPS ...
- NSLock线程锁的使用测试
测试1:NSLock线程锁是不是单例? 打印: 结论1:NSLock不是单例 测试2:同一个线程锁在不同的地方锁定,是否会有锁定两个? 打印为: 结论2:顺序打印,在不同的地方锁定也可以锁定. 测试3 ...
- eval回显变量
eval命令将会首先扫描命令行进行所有的置换,然后再执行该命令.该命令适用于那些一次扫描无法实现其功能的变量. 一个应用场景如下: export path="/home/bin/" ...
- NopCommerce 框架系列(二)
这一篇,让我们一起来认识一下 NopCommerce 的整体目录结构
- android Activity类中的finish()、onDestory()和System.exit(0) 三者的区别
android Activity类中的finish().onDestory()和System.exit(0) 三者的区别 Activity.finish() Call this when your a ...
- 用datagrid实现完整的一个页面
打怪升级真的好难,记录一点一滴,一滴一点,先上效果图. 1.想完成一个界面,先得有界面.界面是在WebRoot下的根目录文件中新建的zjqktj.jsp中建立的,再通过java在后台调用数据库取出数据 ...