[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:

  1 /*
  2  * Author:  Yzcstc
  3  * Created Time:  2014/11/8 19:03:57
  4  * File Name: klo.cpp
  5  */
  6 #include<cstdio>
  7 #include<iostream>
  8 #include<cstring>
  9 #include<cstdlib>
 10 #include<cmath>
 11 #include<algorithm>
 12 #include<string>
 13 #include<map>
 14 #include<set>
 15 #include<vector>
 16 #include<queue>
 17 #include<stack>
 18 #include<ctime>
 19 #define repf(i, a, b) for (int i = (a); i <= (b); ++i)
 20 #define M0(x)  memset(x, 0, sizeof(x))
 21 #define Inf  0x7fffffff
 22 using namespace std;
 23 const int maxn = 120000;
 24 typedef long long ll;
 25 int n, k;
 26 int a[101010];
 27 #define L ch[x][0]
 28 #define R ch[x][1]
 29 #define KT ch[ch[root][0]][1]
 30 struct SplayTree{
 31       int sz[maxn], pre[maxn], ch[maxn][2], v[maxn];
 32       ll sum[maxn];
 33       int m, root;
 34       void push_up(const int& x){
 35            sz[x] = sz[L] + sz[R] + 1;
 36            sum[x] = sum[L] + sum[R] + v[x];
 37       }
 38       void init(){
 39            M0(sz), M0(pre), M0(ch), M0(ch), M0(v);
 40       }
 41       void push_down(const int& x){
 42       }
 43       void rotate(int &x, const int f){
 44             int y = pre[x], z = pre[y];
 45             push_down(y), push_down(x);
 46             ch[y][!f] = ch[x][f];
 47             pre[ch[x][f]] = y;
 48             pre[x] = pre[y];
 49             if (z) ch[z][ch[z][1] == y] = x;
 50             ch[x][f] = y;
 51             pre[y] = x;
 52             push_up(y);
 53       }
 54       void splay(int &x, const int g){
 55             push_down(x);
 56             while (pre[x] != g){
 57                 int y = pre[x], z = pre[y];
 58                 if (z == g) rotate(x, ch[y][0] == x);
 59                 else {
 60                      int f = (ch[z][0] == y);
 61                      ch[y][!f] ? rotate(y, f) : rotate(x, !f);
 62                      rotate(x, f);
 63                 }
 64             }
 65             push_up(x);
 66             if (!g) root = x;
 67       }
 68       void rto(int k,const int g, int& y){
 69             int x = root;
 70             while (sz[L] + 1 != k){
 71                   push_down(x);
 72                   if (sz[L] >= k) x = L;
 73                   else {
 74                        k -= sz[L] + 1;
 75                        x = R;
 76                   }
 77             }
 78             y = x;
 79             splay(x, g);
 80       }
 81       int search(int x, int val){
 82             int y = -1;
 83             while (x){
 84                  y = x;
 85                  if (val <= v[x]) y = x, x = L;
 86                  else y = x, x = R; 
 87             }
 88             return y;
 89       }
 90       void insert(int x, int val){
 91            int y = search(root, val);
 92            ch[y][val > v[y]] = x;
 93            pre[x] = y;
 94            while (y) push_up(y), y = pre[y];
 95            splay(x, 0); 
 96       }
 97       int findpre(int x){
 98            x = L;
 99            while (R) x = R;
100            return x;
101       }
102       void split(int x){
103            splay(x, 0);
104            int lt = findpre(x);
105            if (lt){
106                   splay(lt, x);
107                   root = lt, pre[root] = 0;
108                   ch[root][1] = R;
109                   if (R) pre[R] = root;
110            } else root = R, pre[R] = 0;
111            push_up(root);
112            L = R = 0;
113       }
114       ll query(const int& n, int &vv){
115             int k = (n+1) / 2, x;
116             if (!(n & 1)) ++k;
117             rto(k, 0, x);
118             ll res = (ll)v[x] * (k-1) - sum[ch[root][0]] + sum[ch[root][1]] - (ll)v[x] * (n-k);
119             vv = v[x];
120             return res; 
121       }
122 } S;
123 
124 void init(){
125      for (int i = 1; i <= n; ++i)
126             scanf("%d", &a[i]);
127 }
128 
129 void solve(){
130      if (k == 1){
131            puts("0");
132            for (int i = 1; i <= n; ++i)
133                printf("%d\n", a[i]);
134            return;      
135      }
136      S.root = 1, S.sz[1] = 1, S.sum[1] = S.v[1] = a[1];
137      for (int i = 2; i <= n; ++i)
138            S.sz[i] = 1, S.v[i] = S.sum[i] = a[i];
139      for (int i = 2; i <= k; ++i)
140            S.insert(i, a[i]);
141      int ans_pos = 1, ans_val = 0, val;
142      ll ans = S.query(k, ans_val), tmp;
143      for (int i = k + 1; i <= n; ++i){
144             S.split(i-k);
145             S.insert(i, a[i]);
146             tmp = S.query(k, val);
147             if (tmp < ans)
148                  ans = tmp, ans_val = val, ans_pos = i - k + 1;
149      }
150      cout << ans << endl;
151      for (int i = ans_pos; i <= ans_pos+k-1; ++i) a[i] = ans_val;
152      for (int i = 1; i <= n; ++i) printf("%d\n", a[i]);
153 }
154 
155 int main(){
156 //    freopen("a.in", "r", stdin);
157 //    freopen("a.out", "w", stdout);
158     while (scanf("%d%d", &n, &k) != EOF){
159           init();
160           solve();
161     }
162     return 0;
163 }
View Code

题意:有 n(n<=1000)个串,每个串的程度都<=100,有 m 次操作,每次操作都是将第 p1个串的第 w1 个字母和第 p2 个串的第 w2 个字母交换,问对于每一个串 i,在这些操作执行的过程中,它最多几个串相同过。

思路:由于每个串只有100,我们可以用n*m的时间进行hash。。

        那么剩下来就是直接维护hash值为某一个数的集合了。。。平衡树可维护。。

code:

  1 /*
  2  * Author:  Yzcstc
  3  * Created Time:  2014/11/8 13:53:39
  4  * File Name: poc.cpp
  5  */
  6 #include<cstdio>
  7 #include<iostream>
  8 #include<cstring>
  9 #include<cstdlib>
 10 #include<cmath>
 11 #include<algorithm>
 12 #include<string>
 13 #include<map>
 14 #include<set>
 15 #include<vector>
 16 #include<queue>
 17 #include<stack>
 18 #include<ctime>
 19 #define M0(x)  memset(x, 0, sizeof(x))
 20 #define Inf  0x7fffffff
 21 using namespace std;
 22 #define M 10003
 23 const int maxn = 201000;
 24 /*** splay-tree***/
 25 #define L ch[x][0]
 26 #define R ch[x][1]
 27 int sz[maxn], pre[maxn], rt[maxn], ms[maxn], ch[maxn][2], lz[maxn];
 28 
 29 void Splay_init(){
 30      M0(sz), M0(pre), M0(rt), M0(ms),  M0(ch), M0(lz);
 31 }
 32 
 33 void pushdown(const int &x){
 34      if (lz[x]){
 35           if (L) lz[L] = max(lz[L], lz[x]), ms[L] = max(ms[L], lz[x]);
 36           if (R) lz[R] = max(lz[R], lz[x]), ms[R] = max(ms[R], lz[x]);
 37           lz[x] = 0;
 38      }
 39 }
 40 
 41 void pushup(int x){}
 42 
 43 void rotate(int &x, const int f){
 44      int y = pre[x], z = pre[y];
 45      pushdown(y), pushdown(x);
 46      ch[y][!f] = ch[x][f];
 47      pre[ch[x][f]] = y;
 48      pre[x] =  pre[y];
 49      if (z) ch[z][ch[z][1] == y] = x;
 50      ch[x][f] = y;
 51      pre[y] = x;
 52      pushup(y); 
 53 }
 54 
 55 void splay(int &x, const int g, int &root){
 56      pushdown(x);
 57      while (pre[x] != g){
 58           int y = pre[x],  z = pre[y];
 59           if (z == g) rotate(x, ch[y][0] == x);
 60           else {
 61                int f = (ch[z][0] == y);
 62                ch[y][!f] ? rotate(y, f) : rotate(x, !f);
 63                rotate(x, f);
 64           }
 65      }
 66      pushup(x);
 67      if (!g) root = x;
 68 }
 69 
 70 void update(int &root, int s){
 71      lz[root] = max(lz[root], s);
 72      ms[root] = max(ms[root], s);
 73 }
 74 
 75 int right(int x){
 76      while (R) x = R;
 77      return x;
 78 }
 79 
 80 void insert(int& root, int x, int size){
 81      int p = right(root);
 82      splay(p, 0, root);
 83      ch[p][1] = x, pre[x] = p;
 84      update(root, size);
 85 }
 86 
 87 void split(int& root, int x){
 88      splay(x, 0, root);
 89      int lt = ch[x][0];
 90      lt = right(lt);
 91      if (lt){
 92           splay(lt, x, root), root = lt;
 93           if (R) pre[R] = root;
 94           pre[root] = 0, ch[root][1] = R;
 95      } else
 96           root = R, pre[R] = 0;
 97      L = R = 0; 
 98 }
 99 
100 /*** splay-end***/
101 map<int, int> mp;
102 char s[1100][110];
103 int hs[1010], n, m, q, pw[1010];
104 
105 inline int Hash(const char s[]){
106     int res = 0;
107     for (int i = 0; i < m; ++i)
108          res = res * M + s[i];
109     return res;
110 }
111 
112 void init(){
113      pw[m-1] = 1;
114      for (int i = m-2; i >= 0; --i)
115            pw[i] = pw[i+1] * M;
116      for (int i = 1; i <= n; ++i){
117           scanf("%s", s[i]);
118           hs[i] = Hash(s[i]);
119      } 
120 }
121 
122 int f[maxn];
123 void solve(){
124      Splay_init();
125      mp.clear();
126      int tot = 0, u, v;
127      for (int i = 1; i <= n; ++i){
128            u = hs[i], v = mp[u];
129            if (v)
130                   insert(rt[v], i, ++sz[v]);
131            else {
132                   v = mp[u] = ++tot;
133                   sz[v] = 1; rt[v] = i;
134                   update(rt[v], 1);
135            }
136      }
137      int a, x1, b, x2;
138      int h1, h2;
139      while (q--){
140            scanf("%d%d%d%d", &a, &x1, &b, &x2);
141            x1--, x2--;
142            if (a == b){
143                    h1 = hs[a] + pw[x1] * (s[b][x2] - s[a][x1]) + pw[x2] * (s[a][x1] - s[b][x2]);
144                    u = mp[hs[a]], split(rt[u], a);
145                    if (--sz[u] == 0) mp[hs[a]] = rt[u] = 0;
146                    v = mp[h1];
147                    if (v)
148                           insert(rt[v], a,  ++sz[v]);
149                    else {
150                           v = mp[h1] = ++tot;
151                           sz[v] = 1; rt[v] = a;
152                           update(rt[v], 1);
153                    }
154                    hs[a] = h1;
155                    swap(s[a][x1], s[b][x2]);
156                    continue;
157            }
158            h1 = hs[a] + pw[x1] * (s[b][x2] - s[a][x1]);
159            h2 = hs[b] + pw[x2] * (s[a][x1] - s[b][x2]);
160            u = mp[hs[a]], split(rt[u], a);
161            if (--sz[u] == 0) mp[hs[a]] = rt[u] = 0;
162            u = mp[hs[b]], split(rt[u], b);
163            if (--sz[u] == 0) mp[hs[b]]= rt[u] = 0;
164            v = mp[h1];
165            if (v)
166                   insert(rt[v], a, ++sz[v]);
167            else {
168                   v = mp[h1] = ++tot;
169                   sz[v] = 1; rt[v] = a;
170                   update(rt[v], 1);
171            }
172            v = mp[h2];
173            if (v)
174                   insert(rt[v], b, ++sz[v]);
175            else {
176                   v = mp[h2] = ++tot;
177                   sz[v] = 1; rt[v] = b;
178                   update(rt[v], 1);
179            }
180            hs[a] = h1, hs[b] = h2;
181            swap(s[a][x1], s[b][x2]);
182      }
183      for (int i = 1; i <= n; ++i){
184           u = mp[hs[i]];
185           splay(i, 0, rt[u]);
186           f[i] = ms[i];
187      }
188      for (int i = 1; i <= n; ++i)
189             printf("%d\n", f[i]);
190 }
191 
192 int main(){
193 //    freopen("a.in", "r", stdin);
194 //    freopen("a.out", "w", stdout);
195     while (scanf("%d%d%d", &n, &m, &q) != EOF){
196           init();
197           solve();
198     }
199     fclose(stdin); fclose(stdout);
200     return 0;
201 }
View Code

 

posted on 2014-11-08 21:12  yzcstc  阅读(285)  评论(0编辑  收藏  举报