题意:给定一个序列 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的更多相关文章

  1. 【BZOJ1125】【POI2008】poc - splay+哈希

    题意: Description n列火车,每条有l节车厢.每节车厢有一种颜色(用小写字母表示).有m次车厢交换操作.求:对于每列火车,在交换车厢的某个时刻,与其颜色完全相同的火车最多有多少. Inpu ...

  2. [BZOJ1112][POI2008]砖块Klo

    [BZOJ1112][POI2008]砖块Klo 试题描述 N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另 ...

  3. BZOJ 1112: [POI2008]砖块Klo

    1112: [POI2008]砖块Klo Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1736  Solved: 606[Submit][Statu ...

  4. 1112: [POI2008]砖块Klo

    1112: [POI2008]砖块Klo Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1245  Solved: 426[Submit][Statu ...

  5. 【BZOJ1112】[POI2008]砖块Klo Treap

    [BZOJ1112][POI2008]砖块Klo Description N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出 ...

  6. 【BZOJ1125】[POI2008]Poc hash+map+SBT

    [BZOJ1125][POI2008]Poc Description n列火车,每条有l节车厢.每节车厢有一种颜色(用小写字母表示).有m次车厢交换操作.求:对于每列火车,在交换车厢的某个时刻,与其颜 ...

  7. [Bzoj1112][POI2008]砖块Klo(splay)

    1112: [POI2008]砖块Klo Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2353  Solved: 831[Submit][Statu ...

  8. [BZOJ 1112] [POI2008] 砖块Klo 【区间K大】

    题目链接:BZOJ - 1112 题目分析 枚举每一个长度为k的连续区间,求出这个区间的最优答案,更新全局答案. 可以发现,这个区间的所有柱子最终都变成这k个数的中位数时最优,那么我们就需要查询这个区 ...

  9. [BZOJ1112] [POI2008] 砖块Klo (treap)

    Description N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另一柱.仓库无限大. 现在希望用最小次 ...

随机推荐

  1. vim--macro

    例: qa some vim command q 这个宏只记录了vim命令到寄存器a中,执行这个宏可以用命令: @a 也可以加上执行次数: 10@a 执行10次 当你执行过一次@a之后,你可以用 @@ ...

  2. iOS8 定位补充

    iOS 8定位补充 iOS 8定位需要修改2个地方 1.info.plist文件中添加NSLocationAlwaysUsageDescription:描述信息 从iOS 8开始,用户定位分两种情况 ...

  3. java中的static使用--静态变量、静态方法

    Java 中的 static 使用之静态变量 大家都知道,我们可以基于一个类创建多个该类的对象,每个对象都拥有自己的成员,互相独立.然而在某些时候,我们更希望该类所有的对象共享同一个成员.此时就是 s ...

  4. dockManager中DockPanel的刷新问题!

    使用的是DevExpress的dockManager控件,新增一个DockPanel,在DockPanel中添加一个AxMapControl控件并设置默认加载地图. 实现效果图如下: 但是存在一个问题 ...

  5. margin 碰到过的重叠问题

    双倍margin 稍微记录一下,因为常忘 float + margin,实际边距会变成设置值的双倍. 解决办法是 将元素设为 display:inline 最好要了解 IE的 haslayout 问题 ...

  6. docke部署mysql

    #1    docker pull mysql #2    docker run -v /data/var/mysql/:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=k ...

  7. 《笨办法学C》笔记之基础语法

    这篇笔记不怎么系统,只记录自己比较生疏的知识 变量定义 类型 定义 格式化符号 备注 整数 int %d 长整型 long %ld 单精度浮点 float %f 双精度浮点 double %f 字符 ...

  8. 基于御安全APK加固的游戏反外挂方案

    一. 前言 随着移动互联网的兴起,移动游戏市场近几年突然爆发,收入规模快速增长.根据第三方数据统计,国内移动游戏2015年市场规模已达514.6亿.由于手游市场强势兴起,而且后续增长势头会愈加猛烈.火 ...

  9. 00024500-0000-0000-C000-000000000046错误,在sys.web配置节添加一个用户给web站点。

    <identity impersonate ="true" userName="administrator" password="123456& ...

  10. Android数据库安全解决方案,使用SQLCipher进行加解密

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/11952409 我们都知道,Android系统内置了SQLite数据库,并且提供了一 ...