开始PHD生涯,好久不做题了,手生的不行,代码能力、算法能力直线下滑。
不管以后我做什么方向,做做题目能很好地锻炼我的思维,所以以后开始继续做题,纯粹为了玩!
先整理一下线段树方面的题目吧,最近项目有用到,还有一些新的线段树的题目陆续添加吧
1、单点更新,区间查询
/*
HDU1166
单点更新,对区间进行询问。
不必设置延迟标记,单点更新到叶子节点,正常进行区间查询
*/
#include
#include
#include
#include
using namespace std;
#define LL(x) (x << 1)
#define RR(x) ((x << 1) | 1)
struct Seg_Tree_Node
{
int left, right;
int sum;
int mid()
{
return (left + right) / 2;
}
}tree[50000 * 3 + 12345];
int num[50000 + 123];
void update_info(int idx)
{
tree[idx].sum = tree[LL(idx)].sum + tree[RR(idx)].sum;
}
void build(int l, int r, int idx)
{
tree[idx].left = l;
tree[idx].right = r;
if(l == r)
{
tree[idx].sum = num[l];
return;
}
int mid = tree[idx].mid();
build(l, mid, LL(idx));
build(mid + 1, r, RR(idx));
update_info(idx);
}
void update(int x, int idx, int c)
{
if(tree[idx].left == tree[idx].right)
{
tree[idx].sum += c;
return;
}
int mid = tree[idx].mid();
if(x <= mid) update(x, LL(idx), c);
else update(x, RR(idx), c);
update_info(idx);
}
int query(int l, int r, int idx)
{
if(l <= tree[idx].left && tree[idx].right <= r)
{
//printf("%d -> %d\n", tree[idx].left, tree[idx].right);
return tree[idx].sum;
}
int mid = tree[idx].mid();
if(r <= mid) return query(l, r, LL(idx));
else if(l > mid) return query(l, r, RR(idx));
else return query(l, r, LL(idx)) + query(l, r, RR(idx));
}
int main()
{
int T;
int cas = 1;
scanf("%d", &T);
while(T--)
{
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &num[i]);
build(1, n, 1);
printf("Case %d:\n", cas++);
char s[10];
int x, y;
while(1)
{
scanf("%s", s);
if(strcmp(s, "End") == 0) break;
else if(strcmp(s, "Query") == 0)
{
scanf("%d%d", &x, &y);
if(x > y)
{
int temp = x;
x = y;
y = temp;
}
printf("%d\n", query(x, y, 1));
}
else if(strcmp(s, "Sub") == 0)
{
scanf("%d%d", &x, &y);
update(x, 1, -y);
}
else if(strcmp(s, "Add") == 0)
{
scanf("%d%d", &x, &y);
update(x, 1, y);
}
}
}
return 0;
}
/*
HDU1754
单点更新,区间查询
*/
#include
#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
using namespace std;
struct Seg_Tree
{
int left,right,num;
int calmid() { return (right+left)/2;}
}tree[600020];
int num[200010];
int build(int left,int right,int idx)
{
tree[idx].left=left;
tree[idx].right=right;
if(left==right)
{
return tree[idx].num=num[left];
}
int mid=tree[idx].calmid();
return tree[idx].num=max(build(left,mid,LL(idx)),build(mid+1,right,RR(idx)));
}
void update(int id,int x,int idx)
{
if(tree[idx].left==tree[idx].right)
{
tree[idx].num=x;
return ;
}
int mid=tree[idx].calmid();
if(id<=mid) update(id,x,LL(idx));
else update(id,x,RR(idx));
tree[idx].num=max(tree[LL(idx)].num,tree[RR(idx)].num);
}
int query(int left,int right,int idx)
{
if(left<=tree[idx].left && right>=tree[idx].right) return tree[idx].num;
int mid=tree[idx].calmid();
if(right<=mid) return query(left,right,LL(idx));
else if(left>mid) return query(left,right,RR(idx));
else return max(query(left,mid,LL(idx)),query(mid+1,right,RR(idx)));
}
int main()
{
int n,m,a,b;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;i++)
scanf("%d",&num[i]);
build(1,n,1);
for(int i=1;i<=m;i++)
{
char str[10];
scanf("%s%d%d",&str,&a,&b);
if(str[0]=='Q') printf("%d/n",query(a,b,1));
else update(a,b,1);
}
}
return 0;
}
2、区间更新,区间查询
/*
HDU 1698
区间更新
*/
#include
#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
struct Seg_Tree
{
int left,right,num;
int calmid() {
return (left+right)/2;
}
} tree[300005];
void build(int left,int right,int idx)
{
tree[idx].left=left;
tree[idx].right=right;
tree[idx].num=1;
if(left==right) return ;
int mid=tree[idx].calmid();
if(left<=mid) build(left,mid,LL(idx));
if(right>mid) build(mid+1,right,RR(idx));
}
void update(int left,int right,int x,int idx)
{
if(left<=tree[idx].left && right>=tree[idx].right)
{
tree[idx].num=x;
return;
}
if(tree[idx].num!=-1)
{
tree[RR(idx)].num=tree[LL(idx)].num=tree[idx].num;
tree[idx].num=-1;
}
int mid=tree[idx].calmid();
if(left<=mid) update(left,right,x,LL(idx));
if(right>mid) update(left,right,x,RR(idx));
}
int query(int left,int right ,int idx)
{
if(left<=tree[idx].left && right>=tree[idx].right)
{
if(tree[idx].num!=-1)
return tree[idx].num*(tree[idx].right-tree[idx].left+1);
}
int mid=tree[idx].calmid();
if(right<=mid) return query(left,mid,LL(idx));
else if(left>mid) return query(mid+1,right,RR(idx));
else
return query(left,mid,LL(idx))+query(mid+1,right,RR(idx));
}
int main()
{
int T,cas=1;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d",&n);
build(1,n,1);
scanf("%d",&m);
while(m--)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
update(a,b,c,1);
}
printf("Case %d: The total value of the hook is %d./n",cas++,query(1,n,1));
}
return 0;
}
/*
POJ3468
成段更新,总区间求和
*/
#include
#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
struct Seg_tree
{
int left,right;
__int64 sum,add;//用于标记下传,否则必TLE
int clamid() { return (left+right)/2; }
}tree[100001*3];
int num[100001];
int n,q;
void build(int l,int r,int idx)
{
tree[idx].left=l;
tree[idx].right=r;
tree[idx].add=0;
if(l==r)
{
tree[idx].sum=num[l];
return ;
}
int mid=tree[idx].clamid();
build(l,mid,LL(idx));
build(mid+1,r,RR(idx));
tree[idx].sum=tree[LL(idx)].sum+tree[RR(idx)].sum;
}
void Update(int l,int r,int idx,int c)
{
if(l<=tree[idx].left&&r>=tree[idx].right)
{
tree[idx].add+=c;
tree[idx].sum+=c*(tree[idx].right-tree[idx].left+1);
return ;
}
if(tree[idx].add)
{
tree[LL(idx)].add+=tree[idx].add;
tree[LL(idx)].sum+=tree[idx].add*(tree[LL(idx)].right-tree[LL(idx)].left+1);
tree[RR(idx)].add+=tree[idx].add;
tree[RR(idx)].sum+=tree[idx].add*(tree[RR(idx)].right-tree[RR(idx)].left+1);
tree[idx].add=0;
}
int mid=tree[idx].clamid();
if(r>mid) Update(l,r,RR(idx),c);
if(l<=mid) Update(l,r,LL(idx),c);
/*if(r>mid) Update(mid+1,r,RR(idx),c);
if(l<=mid) Update(l,mid,LL(idx),c);这是错误的*/
tree[idx].sum=tree[LL(idx)].sum+tree[RR(idx)].sum;
}
__int64 query(int l,int r,int idx)
{
if(l<=tree[idx].left&&r>=tree[idx].right)
return tree[idx].sum;
if(tree[idx].add)
{
tree[LL(idx)].add+=tree[idx].add;
tree[LL(idx)].sum+=tree[idx].add*(tree[LL(idx)].right-tree[LL(idx)].left+1);
tree[RR(idx)].add+=tree[idx].add;
tree[RR(idx)].sum+=tree[idx].add*(tree[RR(idx)].right-tree[RR(idx)].left+1);
tree[idx].add=0;
}
int mid=tree[idx].clamid();
if(r<=mid) return query(l,r,LL(idx));
else
if(l>mid) return query(l,r,RR(idx));
else
return query(l,mid,LL(idx))+query(mid+1,r,RR(idx));
}
int main()
{
while(scanf("%d%d",&n,&q)!=EOF)
{
for(int i=1;i<=n;i++) scanf("%d",&num[i]);
build(1,n,1);
for(int i=1;i<=q;i++)
{
char str[10];
int a,b,c;
scanf("%s",str);
if(str[0]=='Q')
{
scanf("%d%d",&a,&b);
printf("%I64d/n",query(a,b,1));
}
else
{
scanf("%d%d%d",&a,&b,&c);
Update(a,b,1,c);
}
}
}
return 0;
}
/*
POJ2777
很裸的区间更新,区间查询
设置一个延迟标记,尽可能减少访问子节点次数
因为最多只有30种颜色,所以使用int类型进行位压缩
*/
#include
#include
#include
#include
using namespace std;
#define LL(x) (x << 1)
#define RR(x) ((x << 1) | 1)
struct Seg_Tree_Node
{
int left, right;
int color;
bool delay;
int mid()
{
return (left + right) / 2;
}
}tree[100000 * 3 + 1234];
int cnum;
void update_info(int idx)
{
tree[idx].color = tree[LL(idx)].color | tree[RR(idx)].color;
}
void pushDown(int idx)
{
tree[LL(idx)].color = tree[idx].color;
tree[LL(idx)].delay = 1;
tree[RR(idx)].color = tree[idx].color;
tree[RR(idx)].delay = 1;
tree[idx].delay = 0;
tree[idx].color = 0;
}
void build(int l, int r, int idx)
{
tree[idx].left = l;
tree[idx].right = r;
tree[idx].color = 1;
tree[idx].delay = 0;
if(l == r) return;
int mid = tree[idx].mid();
build(l, mid, LL(idx));
build(mid + 1, r, RR(idx));
update_info(idx);
}
void update(int l, int r, int idx, int c)
{
if(l <= tree[idx].left && tree[idx].right <= r)
{
tree[idx].color = 1 << (c - 1);
tree[idx].delay = 1;//打上延迟标记
return;
}
if(tree[idx].delay) pushDown(idx);
int mid = tree[idx].mid();
if(r > mid) update(l, r, RR(idx), c);
if(l <= mid) update(l, r, LL(idx), c);
update_info(idx);
}
void query(int l, int r, int idx)
{
if(l <= tree[idx].left && tree[idx].right <= r)
{
cnum = cnum | tree[idx].color;
return;
}
if(tree[idx].delay) pushDown(idx);
int mid = tree[idx].mid();
if(r > mid) query(l, r, RR(idx));
if(l <= mid) query(l, r, LL(idx));
update_info(idx);
}
int cal(int num)
{
int sum = 0;
while(num != 0)
{
if(num & 1) sum++;
num = num >> 1;
}
return sum;
}
int main()
{
int l, t, o;
while(scanf("%d%d%d", &l, &t, &o) != EOF)
{
build(1, l, 1);
char s[10];
int l, r, c;
for(int i = 0; i < o; i++)
{
scanf("%s", s);
if(s[0] == 'P')
{
scanf("%d%d", &l, &r);
if(l > r)
{
int temp = l;
l = r;
r = temp;
}
cnum = 0;
query(l, r, 1);
printf("%d\n", cal(cnum));
}
else
{
scanf("%d%d%d", &l, &r, &c);
if(l > r)
{
int temp = l;
l = r;
r = temp;
}
update(l, r, 1, c);
}
}
}
return 0;
}
/*
JOJ2445
区间更新,区间查询
这题的不同之处在于建树略微有点特别。
先用静态链表建好原始二叉树,接着DFS一遍找出每个父亲节点的管辖范围,类似于后序遍历
另外,这个题目左右子树互换不影响结果
*/
#include
#include
#include
#include
using namespace std;
#define LL(x) (x << 1)
#define RR(x) ((x << 1) | 1)
const int MAXN = 20000 + 1234;
struct EDGE
{
int u, v, next;
}edge[MAXN * 2];
struct Seg_Tree_Node
{
int left, right;
int sum;
bool delay;
int mid()
{
return (left + right) / 2;
}
}tree[MAXN * 3];
int head[MAXN];
int cnt;
int vnum;
bool vis[MAXN];
int lid[MAXN], rid[MAXN];
void addedge(int a, int b)
{
edge[cnt].u = a;
edge[cnt].v = b;
edge[cnt].next = head[a];
head[a] = cnt++;
}
int dfs(int u)
{
int lmin = MAXN;
vis[u] = 1;//�Ѿ��߹���
for(int p = head[u]; p != -1; p = edge[p].next)
{
if(vis[edge[p].v]) continue;
int t = dfs(edge[p].v);
if(t < lmin) lmin = t;
}
rid[u] = ++vnum;
if(lmin == MAXN) lmin = rid[u];
lid[u] = lmin;
return lmin;
}
void build(int l, int r, int idx)
{
tree[idx].left = l;
tree[idx].right = r;
tree[idx].delay = 0;
tree[idx].sum = 0;
if(l == r) return;
int mid = tree[idx].mid();
build(l, mid, LL(idx));
build(mid + 1, r, RR(idx));
}
void pushDown(int idx)
{
int l = LL(idx), r = RR(idx);
tree[l].sum = (tree[l].right - tree[l].left + 1) - tree[l].sum;
tree[l].delay = 1 - tree[l].delay;
tree[r].sum = (tree[r].right - tree[r].left + 1) - tree[r].sum;
tree[r].delay = 1 - tree[r].delay;
tree[idx].delay = 0;
}
void update_info(int idx)
{
int l = LL(idx), r = RR(idx);
tree[idx].sum = tree[l].sum + tree[r].sum;
}
void update(int l, int r, int idx)
{
if(l <= tree[idx].left && tree[idx].right <= r)
{
tree[idx].sum = (tree[idx].right - tree[idx].left + 1) - tree[idx].sum;
tree[idx].delay = 1 - tree[idx].delay;
return;
}
if(tree[idx].delay) pushDown(idx);
int mid = tree[idx].mid();
if(r > mid) update(l, r, RR(idx));
if(l <= mid) update(l, r, LL(idx));
update_info(idx);
}
int query(int l, int r, int idx)
{
if(l <= tree[idx].left && tree[idx].right <= r)
{
return tree[idx].sum;
}
if(tree[idx].delay) pushDown(idx);
int mid = tree[idx].mid();
if(r <= mid) return query(l, r, LL(idx));
else if(l > mid) return query(l, r, RR(idx));
else return query(l, r, LL(idx)) + query(l, r, RR(idx));
update_info(idx);
}
int main()
{
int n, m;
while(scanf("%d", &n) != EOF)
{
cnt = 0;
vnum = 0;
memset(head, -1, sizeof(head));
memset(vis, 0, sizeof(vis));
memset(lid, 0, sizeof(lid));
memset(rid, 0, sizeof(rid));
int a, b;
for(int i = 1; i < n; i++)
{
scanf("%d%d", &a, &b);
addedge(a, b);
addedge(b, a);
}
dfs(1);
//for(int i = 1; i <= n; i++) printf("%d: %d %d\n", i, lid[i], rid[i]);
build(1, n, 1);
scanf("%d", &m);
char str[10];
int x;
for(int i = 0; i < m; i++)
{
scanf("%s", str);
if(str[0] == 'Q')
{
scanf("%d", &x);
printf("%d\n", query(lid[x],rid[x], 1));
}
else
{
scanf("%d", &x);
update(lid[x], rid[x], 1);
}
}
}
return 0;
}
/*
树状数组+二分同样可做
当然这题目数据量小,暴力都能过
纯粹套一下线段树的做法
属于单点更新和区间查询
线段树记录每段线段的和,访问略微有点特殊
访问可以看作是,问当和为x的时候,是第几个数
接着更新和访问一起就可以了
*/
#include
#include
#include
#include
using namespace std;
#define LL(x) (x << 1)
#define RR(x) ((x << 1) | 1)
const int MAXN = 10000;
int rid[MAXN];
int num[MAXN];
struct Seg_Tree_Node
{
int left, right;
int sum;
int mid()
{
return (left + right) / 2;
}
}tree[MAXN * 3];
void update_info(int idx)
{
tree[idx].sum = tree[LL(idx)].sum + tree[RR(idx)].sum;
}
void build(int l, int r, int idx)
{
tree[idx].left = l;
tree[idx].right = r;
if(l == r)
{
tree[idx].sum = 1;
return;
}
int mid = tree[idx].mid();
build(l, mid, LL(idx));
build(mid + 1, r, RR(idx));
update_info(idx);
}
//查询和修改统一
int query(int c, int idx)
{
int ans;
if(tree[idx].left == tree[idx].right)
{
tree[idx].sum = 0;
return tree[idx].left;
}
int mid = tree[idx].mid();
if(tree[LL(idx)].sum >= c) ans = query(c, LL(idx));
else ans = query(c - tree[LL(idx)].sum, RR(idx));
update_info(idx);
return ans;
}
int main()
{
int n;
while(scanf("%d", &n) != EOF)
{
for(int i = 2; i <= n; i++) scanf("%d", &rid[i]);
build(1, n, 1);
for(int i = n; i >= 2; i--)
{
num[i] = query(rid[i] + 1, 1);
}
num[1] =query(1, 1);
for(int i = 1; i <= n; i++) printf("%d\n", num[i]);
}
return 0;
}
/*POJ 2528这题目需要离散化,离散化的时候注意一下,相连的数离散化后相差为1,
否则相差为2更新时候使用延迟标记最后询问的时候一次到底*/
#include
#include
#include
#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
using namespace std;
struct T
{
int num,id,flag,t;
} s[20010];
struct Seg_Tree
{
int left,right,col;
int mid() { return (left+right)/2;}
}tree[30010*2*3];
int x[10010],y[10010],ans;
bool flag[20010*3];
bool cmp(T a, T b)
{
return a.num=tree[idx].right)
{
tree[idx].col=c;
return;
}
if(tree[idx].col!=-1)
{
tree[LL(idx)].col=tree[RR(idx)].col=tree[idx].col;
tree[idx].col=-1;
}
int mid=tree[idx].mid();
if(l<=mid) update(l,r,c,LL(idx));
if(r>mid) update(l,r,c,RR(idx));
}
void query(int l,int r,int idx)
{
if(tree[idx].col!=-1)
{
if(!flag[tree[idx].col])
{
ans++;
flag[tree[idx].col]=true;
}
return;//important
}
int mid=tree[idx].mid();
if(l<=mid) query(l,r,LL(idx));
if(r>mid) query(l,r,RR(idx));
}
int main()
{
int T,n;
scanf("%d",&T);
while(T--)
{
memset(flag,false,sizeof(flag));
scanf("%d",&n);
for(int i=0; is[i-1].num) s[i].t=s[i-1].t+2;
else s[i].t=s[i-1].t+1;
}
else
s[i].t=s[i-1].t;
for(int i=0; i<2*n; i++)
if(s[i].flag==0) x[s[i].id]=s[i].t;
else y[s[i].id]=s[i].t;
build(0,s[2*n-1].t,1);
for(int i=0; i
/*
POJ 3667 Hotel
当年的第一道用线段树做区间合并的题目
delay做延迟标记
lval表示左边的最长连续区间
rval表示右边的最长连续区间
lval表示这个线段的最长连续区间
接着维护上面几个变量即可
因为每次查询后都要更新,所以这个query函数里可以暂时不加更新
*/
#include
#include
#include
using namespace std;
#define LL(x) (x << 1)
#define RR(x) ((x << 1) | 1)
const int MAXN = 50000 + 1234;
struct Seg_Tree_Node
{
int left, right;
int delay;
int cval, lval, rval;
int mid()
{
return (left + right) / 2;
}
}tree[MAXN * 3];
void build(int l, int r, int idx)
{
tree[idx].left = l;
tree[idx].right = r;
tree[idx].cval = tree[idx].lval = tree[idx].rval = r - l + 1;
tree[idx].delay = -1;//0 or 1 or -1
if(l == r) return;
int mid = tree[idx].mid();
build(l, mid, LL(idx));
build(mid + 1, r, RR(idx));
}
void pushdown(int idx)
{
int l = LL(idx), r = RR(idx);
tree[l].cval = tree[l].lval = tree[l].rval = tree[idx].delay * (tree[l].right - tree[l].left + 1);
tree[l].delay = tree[idx].delay;
tree[r].cval = tree[r].lval = tree[r].rval = tree[idx].delay * (tree[r].right - tree[r].left + 1);
tree[r].delay = tree[idx].delay;
tree[idx].delay = -1;
}
void update_info(int idx)
{
int l = LL(idx), r = RR(idx);
tree[idx].lval = tree[l].lval;
if(tree[l].lval == tree[l].right - tree[l].left + 1) tree[idx].lval += tree[r].lval;
tree[idx].rval = tree[r].rval;
if(tree[r].rval == tree[r].right - tree[r].left + 1) tree[idx].rval += tree[l].rval;
tree[idx].cval = max(tree[l].cval, tree[r].cval);
tree[idx].cval = max(tree[idx].cval, tree[l].rval + tree[r].lval);
}
void update(int l, int r, int c, int idx)
{
if(l <= tree[idx].left && tree[idx].right <= r)
{
tree[idx].cval = tree[idx].lval = tree[idx].rval = c * (tree[idx].right - tree[idx].left + 1);
tree[idx].delay = c;
return;
}
if(tree[idx].delay != -1) pushdown(idx);
int mid = tree[idx].mid();
if(r > mid) update(l, r, c, RR(idx));
if(l <= mid) update(l, r, c, LL(idx));
update_info(idx);
}
int query(int c, int idx)
{
if(tree[idx].left == tree[idx].right)
{
if(c == 1) return tree[idx].left;
return 0;
}
if(tree[idx].delay != -1) pushdown(idx);
int mid = tree[idx].mid();
int l = LL(idx), r = RR(idx);
if(tree[l].cval >= c) return query(c, LL(idx));
else if(tree[l].rval + tree[r].lval >= c) return tree[l].right - tree[l].rval + 1;
else if(tree[r].cval >= c) return query(c, RR(idx));
else return 0;
}
int main()
{
int n, m;
while(scanf("%d%d", &n, &m) != EOF)
{
build(1, n, 1);
int a, b, c;
for(int i = 0; i < m; i++)
{
scanf("%d", &a);
if(a == 1)
{
scanf("%d", &b);
int ans = query(b, 1);
printf("%d\n", ans);
if(ans != 0) update(ans, ans + b - 1, 0, 1);
}
else
{
scanf("%d%d", &b, &c);
update(b, b + c - 1, 1, 1);
}
//printf("%d\n", tree[1].cval);
}
}
return 0;
}
/*HDU 1540
与前面那题Hotel相似。
单点更新,查询方式稍微有些区别,变化不大。
*/
#include
#include
#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
int stack[50010],n,m;
struct Seg_Tree
{
int l,r;
int cval,lval,rval;
void doit(int st) { cval=lval=rval=( st==1? 0 : dis() ) ;}
int dis() { return (r-l+1) ;}
int mid() { return (l+r)/2 ;}
}tree[50010*3];
int max(int a,int b)
{
if(a>b) return a;
return b;
}
void build(int left,int right,int idx)
{
tree[idx].l=left;
tree[idx].r=right;
tree[idx].doit(0);
if(left==right) return;
int mid=tree[idx].mid();
build(left,mid,LL(idx));
build(mid+1,right,RR(idx));
}
void update(int x,int st,int idx)
{
if(tree[idx].l==tree[idx].r)
{
tree[idx].doit(st);
return ;
}
int mid=tree[idx].mid();
if(x<=mid) update(x,st,LL(idx));
else update(x,st,RR(idx));
tree[idx].cval=max(tree[LL(idx)].rval+tree[RR(idx)].lval,
max(tree[LL(idx)].cval,tree[RR(idx)].cval));
tree[idx].lval=tree[LL(idx)].lval;
tree[idx].rval=tree[RR(idx)].rval;
if(tree[LL(idx)].cval==tree[LL(idx)].dis()) tree[idx].lval+=tree[RR(idx)].lval;
if(tree[RR(idx)].cval==tree[RR(idx)].dis()) tree[idx].rval+=tree[LL(idx)].rval;
}
int query(int x,int idx)
{
if(tree[idx].l==tree[idx].r || tree[idx].cval==0 || tree[idx].cval==tree[idx].dis() )
{
return tree[idx].cval;
}
int mid=tree[idx].mid();
if(x<=mid)
{
if(x>tree[LL(idx)].r-tree[LL(idx)].rval)
//return query(x,LL(idx))+query(tree[RR(idx)].l,RR(idx));
return query(x,LL(idx))+tree[RR(idx)].lval;
else
return query(x,LL(idx));
}
else
{
if(x
/*
其实就是HOTEL的加强版,甚至于HOTEL的3个函数都没有任何变化。
内存共四个指令,第一次是New x就是找一段长为X的最左边的区间,这个和HOTEL是没有区别,还是用那三个函数找到最左边的区间并加以更新,ST=1
第二个指令是Free x就是找一个包含X的区间,咋一看以为要重写一个QUERY函数,其实没有必要,使用VECTOR数组保存下每次占领的区间,并且由于VECTOR是向量,可以删除中间的,并任意在中间加区间,十分方便。那我们现在向量里找到那个区间,接着进行更新,ST=0
第三个指令是Get x就是找到第X个区间的范围,用VECTOR的记录很快就能找到
第四个指令Reset,很方面,更新一下即可
*/
#include
#include
#include
#include
#define LL(x) (x << 1)
#define RR(x) ((x << 1) | 1)
const int MAXN = 50000 + 1234;
using namespace std;
struct EDGE
{
int begin, end;
};
vector que;
struct Seg_Tree
{
int left, right;
int lval, rval, cval;
int delay;
int mid()
{
return (left + right) / 2;
}
} tree[MAXN * 3];
void build(int l, int r, int idx)
{
tree[idx].left = l;
tree[idx].right = r;
tree[idx].lval = tree[idx].rval = tree[idx].cval = tree[idx].right - tree[idx].left + 1;
tree[idx].delay = -1;
if(l == r) return;
int mid = tree[idx].mid();
build(l, mid, LL(idx));
build(mid + 1, r, RR(idx));
}
void pushdown(int idx)
{
int l = LL(idx), r= RR(idx);
tree[l].delay = tree[r].delay = tree[idx].delay;
tree[l].cval = tree[l].lval = tree[l].rval = tree[idx].delay * (tree[l].right - tree[l].left + 1);
tree[r].cval = tree[r].lval = tree[r].rval = tree[idx].delay * (tree[r].right - tree[r].left + 1);
tree[idx].delay = -1;
}
void updateinfo(int idx)
{
int l = LL(idx), r= RR(idx);
tree[idx].cval = max(tree[l].cval, tree[r].cval);
tree[idx].cval = max(tree[idx].cval, tree[l].rval + tree[r].lval);
tree[idx].lval = tree[l].lval;
if(tree[l].lval == tree[l].right - tree[l].left + 1) tree[idx].lval += tree[r].lval;
tree[idx].rval = tree[r].rval;
if(tree[r].rval == tree[r].right - tree[r].left + 1) tree[idx].rval += tree[l].rval;
}
void update(int l, int r, int c, int idx)
{
if(l <= tree[idx].left && tree[idx].right <= r)
{
tree[idx].delay = c;
tree[idx].cval = tree[idx].lval = tree[idx].rval = c * (tree[idx].right - tree[idx].left + 1);
return;
}
if(tree[idx].delay != -1) pushdown(idx);
int mid = tree[idx].mid();
if(l <= mid) update(l, r, c, LL(idx));
if(r > mid) update(l, r, c, RR(idx));
updateinfo(idx);
}
int query(int x, int idx)
{
if(tree[idx].left == tree[idx].right)
{
return tree[idx].left;
}
if(tree[idx].delay != -1) pushdown(idx);
int mid = tree[idx].mid();
int l = LL(idx), r = RR(idx);
if(tree[l].cval >= x) return query(x, l);
else if(tree[l].rval + tree[r].lval >= x) return mid - tree[l].rval + 1;
else if(tree[r].cval >= x) return query(x, r);
else return -1;//no possible
}
int half_search(int x)
{
int left = 0, right = que.size() - 1;
while(left <= right)
{
int mid = (left + right) / 2;
if(que[mid].begin <= x) left = mid + 1;
else right = mid - 1;
}
return left;
//left是第一个begin大于x的区间(不等于),注意特殊情况就是队列为空,只有1个的时候也成立
}
int main()
{
int n, m;
while(scanf("%d%d", &n, &m) != EOF)
{
que.clear();
build(1, n, 1);
char s[10];
int x;
for(int i = 0; i < m; i++)
{
scanf("%s", s);
if(strcmp(s, "New") == 0)
{
scanf("%d", &x);
if(tree[1].cval < x) puts("Reject New");
else
{
EDGE tmp;
tmp.begin = query(x, 1);
tmp.end = tmp.begin + x - 1;
int pos = half_search(tmp.begin);
que.insert(que.begin() + pos, tmp);
update(tmp.begin, tmp.end, 0, 1);
printf("New at %d\n", tmp.begin);
}
}
else if(strcmp(s, "Free") == 0)
{
scanf("%d", &x);
int pos = half_search(x) - 1;
if(pos < 0 || que[pos].end < x) puts("Reject Free");
else
{
update(que[pos].begin, que[pos].end, 1, 1);
printf("Free from %d to %d\n", que[pos].begin, que[pos].end);
que.erase(que.begin() + pos, que.begin() + pos + 1);
}
}
else if(strcmp(s, "Get") == 0)
{
scanf("%d", &x);
if(x > que.size()) puts("Reject Get");
else
{
printf("Get at %d\n", que[--x].begin);
}
}
else
{
puts("Reset Now");
que.clear();
update(1, n, 1, 1);
}
}
puts("");
}
return 0;
}