线段树(HDU - 2871Memory Control)

题目链接
我就觉得这个题是最适合当入门模板题的,23333
功能很多,要求也多,但是都不难想。憨批我写了足足300行?(写着写着彻底放飞自我woc)
最大连续区间的维护请看我的这个博客
另外我的get操作使用了二分(num[i]记录了之前有几个内存块)二分出最前的该内存块。
再者,对于我的Reset操作,使用了一个pflag标记,标记打开,就要先清空该节点,相当于一个延时标记。随用随清空,于是Reset操作这样把1节点的pflag打开就好了,O(1)完成。
下面是ac代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <algorithm>
#include <cstdlib>
#include <queue>
#include <map>
#include <vector>
#define ll long long
using namespace std;
const int N =1e5+5;
int suuf[N];
struct Node
{
    int l, r;
    int sum;
    int add;
    int addl, addr;
    int addp;
    int slp, srp;
    int num;
    bool Pflag = 0;
    bool flag;
    int ls, rs;
}tr[N<<2];
int mx;
void build(int p, int l, int r)
{
    mx = max(mx, p);
    tr[p].l = l; tr[p].r = r;
    tr[p].slp = tr[p].srp = 0;
    tr[p].addl = 0;
    tr[p].addr = 0;
    tr[p].add = -1;
    tr[p].flag = 1;
    tr[p].num = 0;
    tr[p].addp = 0;
    tr[p].Pflag = 0;
    if (l == r)
    {
        tr[p].sum = tr[p].ls = tr[p].rs = 1;
        return;
    }
    int mid = (l + r) >>1;
    build(p<<1, l, mid);
    build(p<<1|1, mid+1, r);
    tr[p].ls = tr[p].rs = tr[p].sum = tr[p<<1].sum + tr[p<<1|1].sum;
}
void che(int p)
{
    if (tr[p].Pflag == 0) return;
    int t = p;
  //  cout << p << endl;
    p = p<<1;
    tr[p].slp = tr[p].srp = 0;
    tr[p].addl = 0;
    tr[p].addr = 0;
    tr[p].add = -1;
    tr[p].flag = 1;
    tr[p].num = 0;
    tr[p].addp = 0;
    tr[p].ls = tr[p].rs = tr[p].sum = tr[p].r - tr[p].l + 1;
    p = t;
    p = p<<1|1;
    tr[p].slp = tr[p].srp = 0;
    tr[p].addl = 0;
    tr[p].addr = 0;
    tr[p].add = -1;
    tr[p].flag = 1;
    tr[p].num = 0;
    tr[p].addp = 0;
    tr[p].ls = tr[p].rs = tr[p].sum = tr[p].r - tr[p].l + 1;
    p = t;
    tr[p<<1].Pflag = 1;
    tr[p<<1|1].Pflag = 1;
    tr[p].Pflag = 0;
}
void spread(int p)
{
    if (tr[p].add == -1) return;
    int l = p<<1, r = p<<1|1;
    tr[l].sum = tr[l].ls = tr[l].rs = tr[p].add * (tr[l].r - tr[l].l + 1);
    tr[r].sum = tr[r].ls = tr[r].rs = tr[p].add * (tr[r].r - tr[r].l + 1);
    tr[l].add = tr[r].add = tr[p].add;
    tr[l].flag = tr[r].flag = tr[p].add;
    if (tr[p].add == 1)
    {
        tr[r].slp = 0;
        tr[r].srp = 0;
        tr[l].slp = 0;
        tr[l].srp = 0;
        tr[r].addl = tr[l].addl= 0;
        tr[r].addr = tr[l].addr = 0;
        tr[p].addr = tr[p].addl = 0;
    }
    else
    {
        tr[r].slp = tr[l].slp = tr[p].addl;
        tr[r].srp = tr[l].srp = tr[p].addr;
        tr[r].addl = tr[l].addl = tr[p].addl;
        tr[r].addr = tr[l].addr = tr[p].addr;
        tr[p].addr = tr[p].addl = 0;
    }
    tr[p].add = -1;
}
void spread_p(int p)
{
    che(p);
    if(tr[p].addp == 0) return;
    tr[p<<1].num += tr[p].addp;
    tr[p<<1|1].num += tr[p].addp;
    tr[p<<1].addp += tr[p].addp;
    tr[p<<1|1].addp += tr[p].addp;
    tr[p].addp = 0;
}
void pushup(int p)
{
    che(p);
    tr[p].sum =max(max(tr[p<<1].sum, tr[p<<1|1].sum), tr[p<<1].rs + tr[p<<1|1].ls);
    tr[p].ls = tr[p<<1].ls;
    tr[p].rs = tr[p<<1|1].rs;
    tr[p].flag = tr[p<<1].flag && tr[p<<1|1].flag;
    if (tr[p<<1].flag) tr[p].ls = tr[p<<1].sum + tr[p<<1|1].ls;
    if (tr[p<<1|1].flag) tr[p].rs = tr[p<<1|1].sum + tr[p<<1].rs;

}
void change_p(int p, int l, int r, int flag)
{
    che(p);
    if (l <= tr[p].l && r >= tr[p].r)
    {
        tr[p].num += flag;
        tr[p].addp += flag;
        return;
    }
    spread(p);
    spread_p(p);
    int mid = (tr[p].r + tr[p].l) >> 1;
    if (l <= mid) change_p(p<<1, l, r, flag);
    if (r > mid) change_p(p<<1|1, l, r, flag);
    pushup(p);
}
void change(int p, int l, int r, bool flag)
{
    che(p);
    if (l <= tr[p].l && r >= tr[p].r)
    {
        tr[p].sum = tr[p].ls = tr[p].rs = flag * (tr[p].r - tr[p].l + 1);
        tr[p].add = flag;
        tr[p].flag = flag;
        tr[p].addl = tr[p].slp = l;
        tr[p].addr = tr[p].srp = r;
        return;
    }
    spread(p);
    spread_p(p);
    int mid = (tr[p].r + tr[p].l) >> 1;
    if (l <= mid) change(p<<1, l, r, flag);
    if (r > mid) change(p<<1|1, l, r, flag);
    pushup(p);
}
int ask(int p, int k)
{
    che(p);
    if (tr[p].l == tr[p].r)
    {
        if (k > tr[p].sum) return 0;
        return tr[p].l;
    }
    int mid = (tr[p].l + tr[p].r) >> 1;
    spread(p);
    spread_p(p);
    if (tr[p<<1].sum >= k) return ask(p<<1, k);
    if (tr[p<<1].rs + tr[p<<1|1].ls >= k) return mid - tr[p<<1].rs + 1;
    else if (tr[p<<1|1].sum >= k) return ask(p<<1|1, k);
    return 0;
}
Node ask_p(int p, int k)
{
    che(p);
    if (tr[p].l == tr[p].r) return tr[p];
    int mid = (tr[p].l + tr[p].r) >> 1;
    spread(p);
    spread_p(p);
    if (k <= mid) return ask_p(p<<1, k);
    return ask_p(p<<1|1, k);
}
void print()
{
    for (int i = 1; i <= mx; i++)
    {
        cout << tr[i].l << " " << tr[i].r << " " << tr[i].sum << endl;
        cout << tr[i].slp << " " << tr[i].srp << " " << tr[i].num << endl;
        cout << "--------" << endl;
    }
    cout << "------------------------" << endl;
}
int main()
{
    int n, m;
    while(cin >> n >> m)
    {
        int cnt = 0;
        build(1, 1, n);
       // print();
        while(m--)
        {
            char op[10];
            scanf("%s", &op);
            if (op[0] == 'N')
            {
                int k;
                scanf("%d", &k);
                int gg = ask(1, k);
                int t;
                Node te;
                //cout << gg << endl;
                if (gg)
                {
                    change(1, gg, gg + k -1, 0);
                    change_p(1, gg, n, 1);
                    printf("New at %d\n", gg);
                    cnt++;
                }
                else
                    puts("Reject New");
            //    for (int i = 1; i <= n; i++)ask_p(1, i);
          //      print();
            }
            else if (op[0]=='F')
            {
                int k;
                scanf("%d", &k);
                Node te = ask_p(1, k);
                if (te.flag == 0)
                {
                    printf("Free from %d to %d\n", te.slp, te.srp);
                    change(1, te.slp, te.srp, 1);
                    if (te.slp <= n)
                        change_p(1, te.slp, n, -1);
                    cnt--;
                }
                else puts("Reject Free");
           //     for (int i = 1; i <= n; i++)ask_p(1, i);
           //     print();
            }
            else if(op[0] == 'G')
            {
                int k;
                scanf("%d", &k);
                if (cnt >= k)
                {
                    int l = 1, r = n;
                    while(l <= r)
                    {
                        int mid = (l + r) >> 1;
                        Node te = ask_p(1, mid);
                        if (te.num >= k) r = mid-1;
                        else l = mid+1;
                    }
                    printf("Get at %d\n", l);
                }
                else puts("Reject Get");
            }
            else
            {
                printf("Reset Now\n");
                tr[1].Pflag = 1;
                tr[1].slp = tr[1].srp = 0;
                tr[1].addl = 0;
                tr[1].addr = 0;
                tr[1].add = -1;
                tr[1].flag = 1;
                tr[1].num = 0;
                tr[1].addp = 0;
                tr[1].ls = tr[1].rs = tr[1].sum = tr[1].r - tr[1].l + 1;
                cnt = 0;
              //  print();
            }
        }
        printf("\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值