HDU 1540 Tunnel Warfare
HDU 4553 约会安排
最大连续区间也是线段树比较套路的做法
维护三个标记
ls,rs,ms
分别表示从当前区间左端点开始的最长连续区间,最长连续区间,右端点开始的最长连续区间
标记主要在push_up中体现
void push_up(int id,int l,int r)
{
tree[id].ml = max(max(tree[id<<1].ml,tree[id<<1|1].ml),tree[id<<1].rl+tree[id<<1|1].ll);
tree[id].ll = tree[id<<1].ll;
if(tree[id<<1].ll == (r+l)/2-l+1) tree[id].ll += tree[id<<1|1].ll;
tree[id].rl = tree[id<<1|1].rl;
if(tree[id<<1|1].rl == r-(r+l)/2) tree[id].rl += tree[id<<1].rl;
}
用左右儿子的三个标记更新父节点的三个标记
首先是ms,显然父节点的ms等于左儿子的ms和右儿子的ms以及左儿子的rs+右儿子的ls这三者的最大值
然后是ls,先把左二子的ls赋给他,再看左二子的ls是否与他的总区间相等,如果相等则再加上右儿子的ls。本质是看左右区间是否连通。
rs同理
HDU 1540 Tunnel Warfare
最大连续区间的裸题
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<stack>
using namespace std;
const int maxn = 5e4+5;
int n,m;
struct node
{
int ll,rl,ml;
}tree[maxn<<2];
void push_up(int id,int l,int r)
{
tree[id].ml = max(max(tree[id<<1].ml,tree[id<<1|1].ml),tree[id<<1].rl+tree[id<<1|1].ll);
tree[id].ll = tree[id<<1].ll;
if(tree[id<<1].ll == (r+l)/2-l+1) tree[id].ll += tree[id<<1|1].ll;
tree[id].rl = tree[id<<1|1].rl;
if(tree[id<<1|1].rl == r-(r+l)/2) tree[id].rl += tree[id<<1].rl;
}
void build(int id,int l,int r)
{
tree[id].ll = tree[id].rl = tree[id].ml = r-l+1;
if(l==r) return ;
int mid = (l+r)>>1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
}
void update(int id,int stl,int str,int x,int c)
{
if(stl==str)
{
tree[id].ll = tree[id].rl = tree[id].ml = c;
return ;
}
int mid = (stl+str)>>1;
if(x<=mid) update(id<<1,stl,mid,x,c);
else update(id<<1|1,mid+1,str,x,c);
push_up(id,stl,str);
}
int query(int id,int stl,int str,int x)
{
if(stl==str || tree[id].ml==str-stl+1 || tree[id].ml==0) return tree[id].ml;
int mid = (stl+str)>>1;
if(x<mid+1 - tree[id<<1].rl) return query(id<<1,stl,mid,x);
if(x>mid + tree[id<<1|1].ll) return query(id<<1|1,mid+1,str,x);
return tree[id<<1].rl + tree[id<<1|1].ll;
}
int main()
{
int x;
char cmd[5];
while(~scanf("%d%d",&n,&m))
{
stack<int> st;
build(1,1,n);
while(m--)
{
scanf("%s",cmd);
if(cmd[0]=='D')
{
scanf("%d",&x);
st.push(x);
update(1,1,n,x,0);
}
else if(cmd[0]=='R')
{
update(1,1,n,st.top(),1);
st.pop();
}
else
{
scanf("%d",&x);
printf("%d\n",query(1,1,n,x));
}
}
}
return 0;
}
HDU 4553 约会安排
比较复杂,维护两种最大连续区间,并且有优先级
nls,nms,nrs分别表示女神可用的最大连续区间
dls,dms,drs分别表示屌丝可用的最大连续区间
查询的时候查询最大可用连续区间长度大于k的左端点
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 1e5+5;
int n,q;
struct node
{
int l,r;
int dls,drs,dms;
int nls,nrs,nms;
inline int len()
{
return r-l+1;
}
}tree[maxn<<2];
void build(int id,int l,int r)
{
tree[id].l = l,tree[id].r = r;
tree[id].dls = tree[id].drs = tree[id].dms = tree[id].len();
tree[id].nls = tree[id].nrs = tree[id].nms = tree[id].len();
if(l==r) return ;
int mid = (l+r)>>1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
}
void push_up(int id)
{
tree[id].dms = max(max(tree[id<<1].dms,tree[id<<1|1].dms),tree[id<<1].drs+tree[id<<1|1].dls);
tree[id].dls = tree[id<<1].dls;
if(tree[id<<1].dls==tree[id<<1].len()) tree[id].dls+=tree[id<<1|1].dls;
tree[id].drs = tree[id<<1|1].drs;
if(tree[id<<1|1].drs==tree[id<<1|1].len()) tree[id].drs+=tree[id<<1].drs;
tree[id].nms = max(max(tree[id<<1].nms,tree[id<<1|1].nms),tree[id<<1].nrs+tree[id<<1|1].nls);
tree[id].nls = tree[id<<1].nls;
if(tree[id<<1].nls==tree[id<<1].len()) tree[id].nls+=tree[id<<1|1].nls;
tree[id].nrs = tree[id<<1|1].nrs;
if(tree[id<<1|1].nrs==tree[id<<1|1].len()) tree[id].nrs+=tree[id<<1].nrs;
}
void push_down(int id)
{
int lson=id<<1,rson=id<<1|1;
if(tree[id].dms==tree[id].len())
{
tree[lson].dls=tree[lson].dms=tree[lson].drs=tree[lson].len();
tree[rson].dls=tree[rson].dms=tree[rson].drs=tree[rson].len();
}
else if(tree[id].dms==0)
{
tree[lson].dls=tree[lson].dms=tree[lson].drs=0;
tree[rson].dls=tree[rson].dms=tree[rson].drs=0;
}
if(tree[id].nms==tree[id].len())
{
tree[lson].nls=tree[lson].nms=tree[lson].nrs=tree[lson].len();
tree[rson].nls=tree[rson].nms=tree[rson].nrs=tree[rson].len();
}
else if(tree[id].nms==0)
{
tree[lson].nls=tree[lson].nms=tree[lson].nrs=0;
tree[rson].nls=tree[rson].nms=tree[rson].nrs=0;
}
}
void update(int id,int l,int r,int op)
{
if(tree[id].l==l && tree[id].r==r)
{
if(op==1)
{
tree[id].dls=tree[id].drs=tree[id].dms=0;
tree[id].nls=tree[id].nrs=tree[id].nms=tree[id].len();
}
if(op==2)
{
tree[id].dls=tree[id].drs=tree[id].dms=0;
tree[id].nls=tree[id].nrs=tree[id].nms=0;
}
if(op==3)
{
tree[id].dls=tree[id].drs=tree[id].dms=tree[id].len();
tree[id].nls=tree[id].nrs=tree[id].nms=tree[id].len();
}
return ;
}
push_down(id);
int mid = (tree[id].l+tree[id].r)>>1;
if(r<=mid) update(id<<1,l,r,op);
else if (l>mid) update(id<<1|1,l,r,op);
else
{
update(id<<1,l,mid,op);
update(id<<1|1,mid+1,r,op);
}
push_up(id);
}
int query(int id,int x,int op)
{
if(tree[id].l==tree[id].r) return tree[id].l;
push_down(id);
if(op==1)
{
if(tree[id].dls>=x) return tree[id].l;
if(tree[id<<1].dms>=x) return query(id<<1,x,op);
if(tree[id<<1].drs+tree[id<<1|1].dls>=x) return tree[id<<1].r-tree[id<<1].drs+1;
return query(id<<1|1,x,op);
}
if(op==2)
{
if(tree[id].nls>=x) return tree[id].l;
if(tree[id<<1].nms>=x) return query(id<<1,x,op);
if(tree[id<<1].nrs+tree[id<<1|1].nls>=x) return tree[id<<1].r-tree[id<<1].nrs+1;
return query(id<<1|1,x,op);
}
}
int main()
{
int t;
int kase=0;
char cmd[10];
int x,l,r;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&q);
build(1,1,n);
printf("Case %d:\n",++kase);
while(q--)
{
scanf("%s",cmd);
if(cmd[0]=='S')
{
scanf("%d%d",&l,&r);
update(1,l,r,3);
printf("I am the hope of chinese chengxuyuan!!\n");
}
else if (cmd[0]=='D')
{
scanf("%d",&x);
if(tree[1].dms>=x)
{
int k = query(1,x,1);
printf("%d,let's fly\n",k);
update(1,k,k+x-1,1);
}
else printf("fly with yourself\n");
}
else
{
scanf("%d",&x);
if(tree[1].dms>=x)
{
int k = query(1,x,1);
printf("%d,don't put my gezi\n",k);
update(1,k,k+x-1,2);
}
else if (tree[1].nms>=x)
{
int k = query(1,x,2);
printf("%d,don't put my gezi\n",k);
update(1,k,k+x-1,2);
}
else printf("wait for me\n");
}
}
}
return 0;
}