BZOJ 4369: [IOI2015]teams分组 单调栈+主席树
这个题的思路还是十分巧妙的.
我们发现我们要查询的区域恰好构成了一个梯形.
然后用那个单调栈去维护折线,并用主席树做二维数点.
code:
#include <cstdio>
#include <algorithm>
#include <stack>
#include <cstring>
#include <vector>
#define N 500009
#define lson s[x].ls
#define rson s[x].rs
#define ll long long
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
int n,tot,tmp;
int rt[N],sor[N],id[N];
struct data
{
int l,r,id;
data(int l=0,int r=0,int id=0):l(l),r(r),id(id){}
}A[N<<1],up[N<<1];
bool cmp(data a,data b)
{
return a.r==b.r?(a.id==b.id?a.l<b.l:a.id<b.id):a.r<b.r;
}
bool cmp2(data a,data b) { return a.l<b.l; }
namespace presist
{
struct node
{
int ls,rs,sum;
}s[N*70];
int newnode() { return ++tot; }
void build(int &x,int l,int r)
{
x=newnode();
if(l==r) return;
int mid=(l+r)>>1;
build(lson,l,mid),build(rson,mid+1,r);
}
int update(int x,int l,int r,int p,int v)
{
int now=newnode();
s[now]=s[x],s[now].sum=s[x].sum+v;
if(l==r) return now;
int mid=(l+r)>>1;
if(p<=mid) s[now].ls=update(lson,l,mid,p,v);
else s[now].rs=update(rson,mid+1,r,p,v);
return now;
}
int query(int x,int l,int r,int L,int R)
{
if(!x||L>R) return 0;
if(l>=L&&r<=R) return s[x].sum;
int mid=(l+r)>>1,re=0;
if(L<=mid) re+=query(lson,l,mid,L,R);
if(R>mid) re+=query(rson,mid+1,r,L,R);
return re;
}
int get(int x,int y,int l,int r,int re)
{
if(l==r) return l;
int mid=(l+r)>>1,p=s[s[x].ls].sum-s[s[y].ls].sum;
if(p>=re) return get(s[x].ls,s[y].ls,l,mid,re);
else return get(s[x].rs,s[y].rs,mid+1,r,re-p);
}
};
struct sta
{
int h,r;
sta(int h=0,int r=0):h(h),r(r){}
};
stack<sta>S;
void solve()
{
int i,j,m,sn=0;
scanf("%d",&m);
for(i=1;i<=m;++i) scanf("%d",&sor[i]),sn+=sor[i];
if(sn>n) { printf("0\n"); return; }
sort(sor+1,sor+1+m);
while(!S.empty()) S.pop();
S.push(sta(tmp,0));
for(i=1;i<=m;++i)
{
int cur=id[sor[i]],remain=sor[i];
while(!S.empty()&&S.top().h<cur) S.pop();
while(remain&&!S.empty())
{
int det=presist::query(rt[sor[i]],1,tmp,cur+1,S.top().h)-presist::query(rt[S.top().r],1,tmp,cur+1,S.top().h);
if(det>=remain)
{
int c=presist::query(rt[sor[i]],1,tmp,1,cur)-presist::query(rt[S.top().r],1,tmp,1,cur);
cur=presist::get(rt[sor[i]],rt[S.top().r],1,tmp,remain+c);
remain=0;
break;
}
else
{
remain-=det;
cur=S.top().h;
S.pop();
}
}
if(S.empty()) { printf("0\n"); return; }
S.push(sta(cur,sor[i]));
}
printf("1\n");
}
int main()
{
// setIO("input");
int i,j,Q,cn=0;
scanf("%d",&n),tmp=n;
for(i=1;i<=n;++i) scanf("%d%d",&A[i].l,&A[i].r),A[i].id=1;
for(i=1;i<=n;++i) A[++tmp].l=0,A[tmp].r=i,A[tmp].id=-1;
sort(A+1,A+1+tmp,cmp);
for(i=1;i<=tmp;++i)
{
if(A[i].id==-1) id[A[i].r]=i;
else A[i].r=i,up[++cn]=A[i];
}
sort(up+1,up+1+n,cmp2),tmp+=2;
presist::build(rt[0],1,tmp);
for(j=i=1;i<=n;++i)
{
rt[i]=rt[i-1];
while(j<=n&&up[j].l==i)
rt[i]=presist::update(rt[i],1,tmp,up[j].r,1),++j;
}
scanf("%d",&Q);
for(i=1;i<=Q;++i) solve();
return 0;
}

浙公网安备 33010602011771号