bzoj1500: [NOI2005]维修数列

正解大概是splay吧,不想写splay用块链过了

旋转、赋值打标记就好了

求MAX-SUM要维护一下每块的 和、最大子段和、前缀和最大最小值

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define SQRTN 750
#define MAXBL 1000
#define MAXN 500003
#define INF (2000 * SQRTN * 2)
typedef struct Block *PBlock;
struct Block
{
    int a[SQRTN << 4];
    int size;
    int hvsm, sm;
    int rev;
    int sum;
    int msum, mmax, mmin, rmax, rmin;
} pool[MAXBL];
PBlock blst[MAXBL]; /*block stack*/
int tblst;          /*top block stack*/
typedef struct List *PList;
struct List
{
    PBlock a;
    PList last, next;
};
void calc(PBlock p)
{
    p->mmin = INF;
    p->msum = p->mmax = -INF;
    int smin = 0, j;
    p->sum = 0;
    for (j = 0; j < p->size; ++j)
    {
        p->sum += p->a[j];
        if (p->mmin > p->sum)
            p->mmin = p->sum;
        if (p->mmax < p->sum)
            p->mmax = p->sum;
        if (p->sum - smin > p->msum)
            p->msum = p->sum - smin;
        if (p->sum < smin)
            smin = p->sum;
    }
    smin = 0;
    p->sum = 0;
    p->rmin = INF, p->rmax = -INF;
    for (j = p->size - 1; j >= 0; --j)
    {
        p->sum += p->a[j];
        if (p->rmin > p->sum)
            p->rmin = p->sum;
        if (p->rmax < p->sum)
            p->rmax = p->sum;
        if (p->sum < smin)
            smin = p->sum;
    }
}
void build(int *a, int n, PList *head, PList *tail)
{
    int i;
    *head = *tail = NULL;
    for (i = 0; i < n;)
    {
        PList p = (PList)malloc(sizeof(struct List));
        p->a = blst[--tblst];
        p->a->size = (i + SQRTN < n ? SQRTN : n - i);
        memcpy(p->a->a, a + i, sizeof(int) * p->a->size);
        p->a->hvsm = p->a->rev = 0;
        calc(p->a);
        p->last = *tail;
        p->next = NULL;
        if (*head == NULL)
            *head = p;
        else
            (*tail)->next = p;
        *tail = p;
        i += p->a->size;
    }
}
void pushflag(PList x)
{
    int i;
    if (x->a->hvsm)
    {
        for (i = 0; i < x->a->size; ++i)
            x->a->a[i] = x->a->sm;
        x->a->hvsm = x->a->rev = 0;
    }
    if (x->a->rev)
    {
        x->a->rev = 0;
        for (i = 0; i * 2 < x->a->size; ++i)
        {
            int t = x->a->a[i];
            x->a->a[i] = x->a->a[x->a->size - i - 1];
            x->a->a[x->a->size - i - 1] = t;
        }
    }
}
PList head, tail;
void split(PList x, int l)
{
    pushflag(x);
    PList p = (PList)malloc(sizeof(struct List));
    p->a = blst[--tblst];
    p->a->size = x->a->size - l;
    p->a->hvsm = p->a->rev = 0;
    memcpy(p->a->a, x->a->a + l, sizeof(int) * p->a->size);
    p->last = x, p->next = x->next;
    if (x->next)
        x->next->last = p;
    x->a->size = l;
    x->next = p;
    calc(p->a);
    calc(x->a);
    if (x == tail)
        tail = p;
}
void merge(PList x)
{
    pushflag(x);
    PList p = x->next;
    pushflag(p);
    memcpy(x->a->a + x->a->size, p->a->a, sizeof(int) * p->a->size);
    x->a->size += p->a->size;
    x->next = p->next;
    if (p->next)
        p->next->last = x;
    calc(x->a);
    if (p == tail)
        tail = x;
    blst[tblst++] = p->a;
    free(p);
}
PList findl(int num)
{
    PList p;
    for (p = head; num > p->a->size; p = p->next)
        num -= p->a->size;
    if (num != 1)
    {
        split(p, num - 1);
        p = p->next;
    }
    return p;
}
PList findr(int num)
{
    PList p;
    for (p = head; num > p->a->size; p = p->next)
        num -= p->a->size;
    if (num != p->a->size)
        split(p, num);
    return p;
}
void balance()
{
    PList i;
    for (i = head; i; i = i->next)
    {
        while (i != tail && i->a->size < SQRTN / 2)
            merge(i);
        if (i->a->size > SQRTN * 2)
            split(i, SQRTN);
    }
}
int n, m;
int a0[MAXN];
void init()
{
    for (tblst = 0; tblst < MAXBL; ++tblst)
        blst[tblst] = pool + tblst;
    scanf("%d%d", &n, &m);
    int i;
    for (i = 0; i < n; ++i)
        scanf("%d", &a0[i]);
    build(a0, n, &head, &tail);
}
void swap(int *a, int *b)
{
    int c = *a;
    *a = *b;
    *b = c;
}
int main()
{
    init();
    while (m--)
    {
        char opt[10];
        scanf("%s", opt);
        if (opt[0] == 'I')
        {
            int pos, tot, i;
            scanf("%d%d", &pos, &tot);
            for (i = 0; i < tot; ++i)
                scanf("%d", &a0[i]);
            PList h2, t2;
            build(a0, tot, &h2, &t2);
            if (head == NULL)
                head = h2, tail = t2;
            else if (pos == 0)
            {
                t2->next = head;
                head->last = t2;
                head = h2;
            }
            else if (pos == n)
            {
                h2->last = tail;
                tail->next = h2;
                tail = t2;
            }
            else
            {
                PList p = findl(pos + 1);
                PList p2 = p->last;
                h2->last = p2;
                p2->next = h2;
                t2->next = p;
                p->last = t2;
            }
            n += tot;
        }
        else if (opt[0] == 'D')
        {
            int dl, dr;
            scanf("%d%d", &dl, &dr);
            dr += dl - 1;
            PList i;
            if (dl == 1 && dr == n)
            {
                for (i = head; i;)
                {
                    blst[tblst++] = i->a;
                    PList j = i->next;
                    free(i);
                    i = j;
                }
                head = tail = NULL;
            }
            else
            {
                PList fr = findl(dl), en = findr(dr);
                if (fr->last)
                    fr->last->next = en->next;
                else
                    head = en->next;
                if (en->next)
                    en->next->last = fr->last;
                else
                    tail = fr->last;
                PList end = en->next;
                for (i = fr; i != end;)
                {
                    blst[tblst++] = i->a;
                    PList j = i->next;
                    free(i);
                    i = j;
                }
            }
            n -= dr - dl + 1;
        }
        else if (opt[0] == 'M' && opt[2] == 'K')
        {
            int dl, dr, c;
            scanf("%d%d%d", &dl, &dr, &c);
            dr += dl - 1;
            PList fr = findl(dl), en = findr(dr), i;
            for (i = fr; i != en->next; i = i->next)
            {
                i->a->hvsm = 1, i->a->sm = c;
                i->a->sum = i->a->size * c;
                if (c < 0)
                {
                    i->a->msum = c;
                    i->a->mmin = i->a->sum;
                    i->a->mmax = c;
                    i->a->rmin = i->a->sum;
                    i->a->rmax = c;
                }
                else
                {
                    i->a->msum = i->a->sum;
                    i->a->mmin = c;
                    i->a->mmax = i->a->sum;
                    i->a->rmin = c;
                    i->a->rmax = i->a->sum;
                }
            }
        }
        else if (opt[0] == 'R')
        {
            int dl, dr;
            scanf("%d%d", &dl, &dr);
            dr += dl - 1;
            PList fr = findl(dl), en = findr(dr);
            while (fr != en && fr != en->next)
            {
                fr->a->rev ^= 1;
                en->a->rev ^= 1;
                swap(&fr->a->mmin, &fr->a->rmin);
                swap(&fr->a->mmax, &fr->a->rmax);
                swap(&en->a->mmin, &en->a->rmin);
                swap(&en->a->mmax, &en->a->rmax);
                PBlock tmp = fr->a;
                fr->a = en->a;
                en->a = tmp;
                fr = fr->next;
                en = en->last;
            }
            if (fr == en)
            {
                fr->a->rev ^= 1;
                swap(&fr->a->mmin, &fr->a->rmin);
                swap(&fr->a->mmax, &fr->a->rmax);
            }
        }
        else if (opt[0] == 'G')
        {
            int dl, dr;
            scanf("%d%d", &dl, &dr);
            dr += dl - 1;
            PList fr = findl(dl), en = findr(dr), i;
            int ans = 0;
            for (i = fr; i != en->next; i = i->next)
                ans += i->a->sum;
            printf("%d\n", ans);
        }
        else if (opt[0] == 'M' && opt[2] == 'X')
        {
            int smin = 0, ans = -INF, sum = 0;
            PList i;
            for (i = head; i; i = i->next)
            {
                if (ans < i->a->msum)
                    ans = i->a->msum;
                if (ans < sum + i->a->mmax - smin)
                    ans = sum + i->a->mmax - smin;
                if (smin > sum + i->a->mmin)
                    smin = sum + i->a->mmin;
                sum += i->a->sum;
            }
            printf("%d\n", ans);
        }
        balance();
    }
    return 0;
}


阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页