[NOIP模拟] 序列操作

来源:互联网 发布:c语言a和a差 编辑:程序博客网 时间:2024/06/01 22:22

About:

    2017.11.06 T2

Solution:

    好气,我这道题写的权值线段树,结果维护的时候搞忘清零了,只有 20 分,加上清零就 A了,当然我是指的评测机上AC,在 OJ 上要 T 一些点,有点小气。
    我用权值线段树,在修改的时候加了一个 log2H, 但我的询问是 log2H 的,比较已经过了的代码修改是 O(H) 询问也是 O(H),我的算法还是被卡了。

Code :

权值线段树

#include <cstdio>#include <cstdlib>#include <cstring>#include <string>#include <algorithm>#include <iostream>#include <cmath>#include <ctime>#include <map>#include <vector>using namespace std;inline int read() {    int i = 0, f = 1;    char ch = getchar();    while(!isdigit(ch)) {        if(ch == '-') f = -1; ch = getchar();    }    while(isdigit(ch)) {        i = (i << 3) + (i << 1) + ch - '0'; ch = getchar();    }    return i * f;}const int MAXH = 1e4 + 5;int h[MAXH], tr[MAXH << 2], MAX, mx;inline void update(int k) {    tr[k] = tr[k << 1] + tr[k << 1 | 1];}inline void build(register int k, register int s, register int t) {    if(s == t) return (void)(tr[k] = h[s]);    int mid = s + t >> 1;    build(k << 1, s, mid);    build(k << 1 | 1, mid + 1, t);    update(k);}inline int query(register int k, register int s, register int t, register int x) {    if(s == t) return s;    int mid = s + t >> 1;    if(tr[k << 1 | 1] >= x) return query(k << 1 | 1, mid + 1, t, x);    else return query(k << 1, s, mid, x - tr[k << 1 | 1]);}inline int querysze(register int k, register int s, register int t, register int l, register int r) {    if(l <= s && t <= r) return tr[k];    int mid = s + t >> 1, res = 0;    if(l <= mid) res = querysze(k << 1, s, mid, l, r);    if(mid < r) res += querysze(k << 1 | 1, mid + 1, t, l, r);    return res;}inline void modify(register int k, register int s, register int t, register int pos, register int x) {    if(s == t) return (void)(tr[k] += x);    int mid = s + t >> 1;    if(pos <= mid) modify(k << 1, s, mid, pos, x);    else modify(k << 1 | 1, mid + 1, t, pos, x);    update(k);}int main() {    int n = read(), m = read();    for(register int i = 1; i <= n; ++i) {        int x = read();        ++h[x + 1], mx = max(mx, x + 1);    }    int MAX = 1e4 + 2;    build(1, 1, MAX);    int flag = 0;    for(register int i = 1; i <= m; ++i) {        int x = read();        int now = query(1, 1, MAX, x);         if(now == 1) {            flag = 1;            cout<<i - 1;            return 0;        }        int sze = querysze(1, 1, MAX, now, mx);        if(now == mx) {            int delta = sze - x;            if(delta)                 modify(1, 1, MAX, now, -x),                 modify(1, 1, MAX, now - 1, x),                 h[now - 1] += x, h[now] -= x;            else                 modify(1, 1, MAX, now, -sze),                 modify(1, 1, MAX, now - 1, sze),                 h[now - 1] += sze, h[now] -= sze, --mx;        }        else {            int delta = sze - x;            int nowsze = h[now];            modify(1, 1, MAX, now, -nowsze + delta),             modify(1, 1, MAX, now - 1, nowsze - delta),            h[now - 1] += nowsze - delta, h[now] = delta;            for(register int i = mx; i >= now + 1; --i) {                if(h[i])                     modify(1, 1, MAX, i, -h[i]),                     modify(1, 1, MAX, i - 1, h[i]);            }            for(int i = now + 1; i <= mx; ++i)                if(h[i]) h[i - 1] += h[i], h[i] = 0;            --mx;        }    }    if(!flag) cout<<m;}

普通的数组,但是AC

#include <cstdio>#include <cstdlib>#include <cstring>#include <string>#include <algorithm>#include <iostream>#include <cmath>#include <ctime>#include <map>#include <vector>using namespace std;inline int read() {    int i = 0, f = 1;    char ch = getchar();    while(!isdigit(ch)) {        if(ch == '-') f = -1; ch = getchar();    }    while(isdigit(ch)) {        i = (i << 3) + (i << 1) + ch - '0'; ch = getchar();    }    return i * f;}const int MAXH = 1e4 + 5;int h[MAXH], tr[MAXH << 2], MAX, mx;inline int find(int x) {    int now = 0;    for(int i = mx; i >= 1; --i) {        now += h[i];        if(now >= x) return i;    }}inline int query(int x) {    int now = 0;    for(int i = mx; i >= x; --i)         now += h[i];    return now;}int main() {    int n = read(), m = read();    for(register int i = 1; i <= n; ++i) {        int x = read();        ++h[x + 1], mx = max(mx, x + 1);    }    int MAX = mx;    int flag = 0;    for(register int i = 1; i <= m; ++i) {        int x = read();        int now = find(x);         if(now == 1) {            flag = 1;            cout<<i - 1;            return 0;        }        int sze = query(now);        if(now == mx) {            int delta = sze - x;            if(delta) h[now - 1] += x, h[now] -= x;            else h[now - 1] += sze, h[now] -= sze, --mx;        }        else {            int delta = sze - x;            int nowsze = h[now];            h[now - 1] += nowsze - delta, h[now] = delta;            for(int i = now + 1; i <= mx; ++i)                h[i - 1] += h[i], h[i] = 0;            --mx;        }    }    if(!flag) cout<<m;}