题目链接
我就觉得这个题是最适合当入门模板题的,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;
}