洛谷P3471 [POI2008]POC-Trains
? 解题记录 ? ? 洛谷 ? ? 线段树 ? ? 哈希 ?    2018-06-25 20:28:33    524    0    0

题目描述

The Trains of Colour Parade begins tomorrow in Byteotia.

Intense preparations are already in progress at the station's auxiliary tracks. There are nn parallel tracks at the station, numbered from 11 to nn . The train no. ii occupies the i^{th}ith track.

Every train consists of ll cars and each car is painted with one of 26 colours (denoted by non-capital letters of the English alphabet).

We say that two trains look the same, if their corresponding cars are painted the same colour.

Throughout the parade a crane will switch places of certain pairs of cars. The real parade, however, will take place tomorrow.

Today the train dispatcher, Byteasar, watched the general rehearsal closely. He even wrote down the sequence of car swaps.

Byteasar particularly dislikes many trains looking the same.

For each train pp he would like to calculate the maximum number of trains that at some moment look the same as the train pp at the very same moment.

Task

Write a programme that:

  • reads descriptions of the trains occupying tracks and the sequence of car swaps,

  • for each train determines the maximum number of trains that look the same as it at certain moment,

  • writes out the result.

给出n个字符串,长度均为len;

有m次操作,每次将两个字符交换;

求每个字符串在任何时点上,与相同的它最多的字符串个数;

输入输出格式

输入格式:

 

The first line of the input contains three integers nn , ll and mm ( 2 \le n \le 10002n1000 , 1 \le l \le 1001l100 , 0 \le m \le 100\ 0000m100 000 ), denoting respectively the number of trains, their common length and the number of car swaps. The following nn lines contain descriptions of the trains on successive tracks. The

k^{th}kth line consists of ll small letters of the English alphabet denoting the colours of successive cars of the k^{th}kth train. Then mm lines describing the car swaps follow, in the order of the swaps. The r^{th}rth line contains four integers p_1p1 , w_1w1 , p_2p2 , w_2w2 ( 1 \le p_1, p_2, \le n1p1,p2,n , 1 \le w_1, w_2 \le l1w1,w2l , p_1 \ne p_2p1p2 or w_1 \ne w_2w1w2 ) denoting the r^{th}rth car swap-the car no. w_1w1 of the train no. p_1p1 is swapped with the car no. w_2w2 of the train no. p_2p2 .

 

输出格式:

 

Your programme should write out exactly nn lines. The $k^[th}$ line should contain one integer-the number of trains looking the same as the train no. kk at certain moment.

 

输入输出样例

输入样例#1: 复制
5 6 7
ababbd
abbbbd
aaabad
caabbd
cabaad
2 3 5 4
5 3 5 5
3 5 2 2
1 2 4 3
2 2 5 1
1 1 3 3
4 1 5 6
输出样例#1: 复制
3
3
3
2
3

说明

The figure presents the successive car swaps:

track 1:  ababbd    ababbd    ababbd    ababbd    aaabbd    aaabbd    aaabbd    aaabbd
track 2:  abbbbd    ababbd    ababbd    aaabbd    aaabbd    acabbd    acabbd    acabbd
track 3:  aaabad -> aaabad -> aaabad -> aaabbd -> aaabbd -> aaabbd -> aaabbd -> aaabbd
track 4:  caabbd    caabbd    caabbd    caabbd    cabbbd    cabbbd    cabbbd    dabbbd
track 5:  cabaad    cabbad    caabbd    caabbd    caabbd    aaabbd    aaabbd    aaabbc
           (0)       (1)       (2)       (3)       (4)       (5)       (6)       (7)

The number of trains looking the same as either of the trains no. 1, 2 or 3 was maximal at time (4) (when all three looked the same). The number of trains looking the same as the train no. 5 was maximal at time (5) and (6). The number of trains looking the same as the train no. 4 was maximal at time (2).

一眼就知道怎么做但是代码十分Dark的数据结构题目。

首先每个串哈希掉,然后每有一个新哈希值,新开一个动态开点线段树记录当前哈希值在每一个时间点上的变化,也可以用平衡树维护。这样我们每一次在一个字符串被修改的时候统计:从它出现在这个哈希值的时间开始一直到当前时间点,该哈希值的最大字符串个数是多少。我们只需要在线段树上记录每一个变更时间点,每一次查询直接查出现时间在线段树中的前驱就行了。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<map>
#define LL unsigned long long
using namespace std;
const int base = 233, inf = 0x7fffffff;
const int maxn = 1e3 + 5, maxl = 1e2 + 5, maxm = 1e5 + 5;
LL pow[maxn], hsh[maxn], lhsa, lhsb;
char s[maxn][maxn];
int n, m, l, ans[maxn];
int a, b, c, d, intime[maxn];
map<LL, int > tot;

namespace SGT {
    #define L 0
    #define R 1
    struct node{int mx, h, ch[2];}
    tree[(maxm << 6)];
    int cnt;
    map<LL, int> root;
    void push_up(int rt) {
        tree[rt].mx = max(tree[tree[rt].ch[0]].mx, tree[tree[rt].ch[1]].mx);
        tree[rt].h = max(tree[tree[rt].ch[0]].h, tree[tree[rt].ch[1]].h);
    }
    void ins(int & rt, int pos, int dt, int tl = 0, int tr = m + 1) {
        if(!rt) rt = ++cnt;
        if(tl == tr) return tree[rt].h = pos, tree[rt].mx = dt, void();
        int mid = tl + tr >> 1;
        if(pos <= mid) ins(tree[rt].ch[L], pos, dt, tl, mid);
        else ins(tree[rt].ch[R], pos, dt, mid + 1, tr);
        push_up(rt);
    }
    int Qmx(int l, int r, int rt, int tl = 0, int tr = m + 1) {
        if(!rt) return 0;
        if(tl == l && tr == r) return tree[rt].mx;
        int mid = tl + tr >> 1;
        if(r <= mid) return Qmx(l, r, tree[rt].ch[L], tl, mid);
        else if(l > mid) return Qmx(l, r, tree[rt].ch[R], mid + 1, tr);
        else return max(Qmx(l, mid, tree[rt].ch[L], tl, mid), Qmx(mid + 1, r, tree[rt].ch[R], mid + 1, tr));
    }
    int Qpre(int l, int r, int rt, int tl = 0, int tr = m + 1) {
        if(!rt) return 0;
        if(l == tl && r == tr) return tree[rt].h;
        int mid = tl + tr >> 1;
        if(r <= mid) return Qpre(l, r, tree[rt].ch[L], tl, mid);
        else if(l > mid) return Qpre(l, r, tree[rt].ch[R], mid + 1, tr);
        else return max(Qpre(l, mid, tree[rt].ch[L], tl, mid), Qpre(mid + 1, r, tree[rt].ch[R], mid + 1, tr));
    }
}

LL Ghsh(char * s, int len) {
    LL ans = 0;
    for(register int i = 0; i < len; ++i)
        ans = ans + pow[i] * s[i];
    return ans;
}

void edit(int a, int b, int c, int d) {
    hsh[a] = hsh[a] - pow[c] * s[a][c];
    hsh[b] = hsh[b] - pow[d] * s[b][d];
    swap(s[a][c], s[b][d]);
    hsh[a] = hsh[a] + pow[c] * s[a][c];
    hsh[b] = hsh[b] + pow[d] * s[b][d];
}

int main() {
    //freopen("tst.in", "r", stdin);
    //freopen("my.out", "w", stdout);
    pow[0] = 1;
    scanf("%d%d%d", &n, &l, &m);
    for(register int i = 1; i <= 1000; ++i) 
        pow[i] = pow[i - 1] * base;
    for(register int i = 1; i <= n; ++i) {
        scanf("%s", s[i]), hsh[i] = Ghsh(s[i], l);
        ++tot[hsh[i]];
    }
    for(register int i = 1; i <= n; ++i) {
        SGT::ins(SGT::root[hsh[i]], 0, tot[hsh[i]]);
    }
    for(register int i = 1; i <= m; ++i) {
        using namespace SGT;
        scanf("%d%d%d%d", &a, &c, &b, &d), --c, --d;
        if(a == b) {
            //cerr << Qpre(0, intime[a], root[hsh[a]]) << endl;
            ans[a] = max(ans[a], Qmx(Qpre(0, intime[a], root[hsh[a]]), i, root[hsh[a]]));
            lhsa = hsh[a], lhsb = hsh[b];
            edit(a, b, c, d);
            if(lhsa != hsh[a]) {
                --tot[lhsa];
                ins(root[lhsa], i, tot[lhsa]);
                ++tot[hsh[a]], intime[a] = i;
                ins(root[hsh[a]], i, tot[hsh[a]]);
            }
            continue;
        }
        lhsa = hsh[a], lhsb = hsh[b];
        ans[a] = max(ans[a], Qmx(Qpre(0, intime[a], root[lhsa]), i, root[lhsa]));
        ans[b] = max(ans[b], Qmx(Qpre(0, intime[b], root[lhsb]), i, root[lhsb]));
        edit(a, b, c, d);
        if(hsh[a] != lhsa) {
            --tot[lhsa], ++tot[hsh[a]];
            ins(root[lhsa], i, tot[lhsa]);
            intime[a] = i;
            ins(root[hsh[a]], i, tot[hsh[a]]);
        }
        if(hsh[b] != lhsb) {
            --tot[lhsb], ++tot[hsh[b]];
            ins(root[lhsb], i, tot[lhsb]);
            intime[b] = i;
            ins(root[hsh[b]], i, tot[hsh[b]]);
        }
    }
    for(register int i = 1; i <= n; ++i) {
        ans[i] = max(ans[i], SGT::Qmx(SGT::Qpre(0, intime[i], SGT::root[hsh[i]]), m, SGT::root[hsh[i]]));
        printf("%d\n", ans[i]);
    }
    return 0;
}


上一篇: HDU5739 Fantasia

下一篇: 洛谷P3563 [POI2013]POL-Polarization

524 人读过
立即登录, 发表评论.
没有帐号? 立即注册
0 条评论
文档导航