将分组计划按照$k$从小到大排序,维护一个单调栈,每个元素为一个矩形,按最底下元素从高到低排列,栈顶最低。

每次加入一个矩形可选区域,维护单调栈,可以往回合并。

然后将所有最低点不满足的矩形取出,合并后放回。

每次考虑栈顶区域,将它取到和下一个矩形底边一致时合并。

可持久化线段树维护,时间复杂度$O((n+s)\log n)$。

#include<cstdio>
#include<algorithm>
const int N=500010,M=200010,P=N*20;
int n,m,k,i,j,x,g[N],v[N],nxt[N],a[M],t;
int val[P],l[P],r[P],tot,T[N];
struct E{int r,l,d,k;E(){}E(int _r,int _l,int _d,int _k){r=_r,l=_l,d=_d,k=_k;}}q[M];
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
int ins(int x,int a,int b,int c){
int y=++tot;val[y]=val[x]+1;
if(a==b)return y;
int mid=(a+b)>>1;
if(c<=mid)l[y]=ins(l[x],a,mid,c),r[y]=r[x];else l[y]=l[x],r[y]=ins(r[x],mid+1,b,c);
return y;
}
int ask(int x,int y,int a,int b,int c,int d){
if(c>d)return 0;
if(c<=a&&b<=d)return val[x]-val[y];
int mid=(a+b)>>1,t=0;
if(c<=mid)t=ask(l[x],l[y],a,mid,c,d);
if(d>mid)t+=ask(r[x],r[y],mid+1,b,c,d);
return t;
}
int low(int x,int y,int a,int b,int c){
if(val[x]==val[y])return 0;
if(a==b)return a;
int mid=(a+b)>>1;
if(c<=mid){
int t=low(l[x],l[y],a,mid,c);
if(t)return t;
}
return low(r[x],r[y],mid+1,b,c);
}
int kth(int x,int y,int c,int k){
k+=ask(x,y,1,n,1,c-1);
int a=1,b=n,mid,t;
while(a<b){
mid=(a+b)>>1;
t=val[l[x]]-val[l[y]];
if(k<=t)x=l[x],y=l[y],b=mid;else k-=t,x=r[x],y=r[y],a=mid+1;
}
return a;
}
inline void merge(){
if(t<2)return;
if(q[t].d>=q[t-1].d){
q[t-1].r=q[t].r;
if(q[t].d==q[t-1].d)q[t-1].k+=q[t].k;
t--;
}
}
inline bool solve(){
read(k);
int sum=0;
for(i=1;i<=k;i++){
read(a[i]);
sum+=a[i];
if(sum>n)return 0;
}
std::sort(a+1,a+k+1);
for(i=1,t=0;i<=k;i++){
int x=a[i],d=low(T[x],T[a[i-1]],1,n,x),l,r=0;
if(d)q[++t]=E(T[x],T[a[i-1]],d,ask(T[x],T[a[i-1]],1,n,d,d)),merge();
while(t&&q[t].d<x){
if(!r)r=q[t].r;
l=q[t--].l;
}
if(r){
d=low(r,l,1,n,x);
if(d)q[++t]=E(r,l,d,ask(r,l,1,n,d,d)),merge();
}
while(x){
if(!t)return 0;
if(t==1){
int now=ask(q[t].r,q[t].l,1,n,q[t].d+1,n)+q[t].k;
if(now<x)return 0;
if(now==x)t--;
else if(q[t].k>x)q[t].k-=x;
else if(q[t].k==x){
q[t].d=low(q[t].r,q[t].l,1,n,q[t].d+1);
q[t].k=ask(q[t].r,q[t].l,1,n,q[t].d,q[t].d);
}else{
x-=q[t].k;
int d=kth(q[t].r,q[t].l,q[t].d+1,x);
int tmp=ask(q[t].r,q[t].l,1,n,q[t].d+1,d-1);
x-=tmp;
int k=ask(q[t].r,q[t].l,1,n,d,d);
if(x<k){
q[t].d=d;
q[t].k=k-x;
}else{
q[t].d=low(q[t].r,q[t].l,1,n,d+1);
q[t].k=ask(q[t].r,q[t].l,1,n,q[t].d,q[t].d);
}
}
break;
}
int now=ask(q[t].r,q[t].l,1,n,q[t].d+1,q[t-1].d-1)+q[t].k;
if(now<=x){
x-=now;
q[t-1].r=q[t].r;
q[t-1].k+=ask(q[t].r,q[t].l,1,n,q[t-1].d,q[t-1].d);
t--;
}else{
if(q[t].k>x)q[t].k-=x;
else if(q[t].k==x){
q[t].d=low(q[t].r,q[t].l,1,n,q[t].d+1);
q[t].k=ask(q[t].r,q[t].l,1,n,q[t].d,q[t].d);
}else{
x-=q[t].k;
int d=kth(q[t].r,q[t].l,q[t].d+1,x);
int tmp=ask(q[t].r,q[t].l,1,n,q[t].d+1,d-1);
x-=tmp;
int k=ask(q[t].r,q[t].l,1,n,d,d);
if(x<k){
q[t].d=d;
q[t].k=k-x;
}else{
q[t].d=low(q[t].r,q[t].l,1,n,d+1);
q[t].k=ask(q[t].r,q[t].l,1,n,q[t].d,q[t].d);
}
}
break;
}
}
}
return 1;
}
int main(){
read(n);
for(i=1;i<=n;i++)read(x),read(v[i]),nxt[i]=g[x],g[x]=i;
for(i=1;i<=n;i++)for(T[i]=T[i-1],j=g[i];j;j=nxt[j])T[i]=ins(T[i],1,n,v[j]);
read(m);
while(m--)puts(solve()?"1":"0");
return 0;
}

  

BZOJ4369 : [IOI2015]teams分组的更多相关文章

  1. BZOJ 4369: [IOI2015]teams分组

    把一个人看成二维平面上的一个点,把一个K[i]看成左上角为(0,+max),右下角为(K[i],K[i])的一个矩阵,那么可以很好地描述人对于询问是否合法(我也不知道他怎么想到这东西的) 然后把一组询 ...

  2. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  3. jquery.autocomplete 模糊查询 支持分组

    //demo <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <lin ...

  4. CBQW ---分组表单展示

    工作流审核表单后,将表单信息展示页面中. Rest读取展示 展示方式有2 一.              CBQW内容查询, 通过CBQW内容查询.分别通过设置itemstyle和header xsl ...

  5. MySQL最常用分组聚合函数

    一.聚合函数(aggregation function)---也就是组函数 在一个行的集合(一组行)上进行操作,对每个组给一个结果. 常用的组函数: AVG([distinct] expr) 求平均值 ...

  6. 【CF1133E】K Balanced Teams(动态规划,单调队列)

    [CF1133E]K Balanced Teams(动态规划,单调队列) 题面 CF 让你把一堆数选一些出来分成不超过\(K\)组,每一组里面的最大值和最小值之差不超过\(5\),求最多有多少个人元素 ...

  7. CF899A Splitting in Teams

    CF899A Splitting in Teams 题意翻译 n个数,只有1,2,把它们任意分组,和为3的组最多多少 题目描述 There were nn groups of students whi ...

  8. Yet Another Division Into Teams

    E. Yet Another Division Into Teams 首先要想明白一个东西,就是当一个小组达到六个人的时候,它一定可以拆分成两个更优的小组. 这个题可以用动态规划来写,用一个数组来保存 ...

  9. CodeForces 1249A --- Yet Another Dividing into Teams

    [CodeForces 1249A --- Yet Another Dividing into Teams] Description You are a coach of a group consis ...

随机推荐

  1. 在DB2 for z/os上创建指定pagesize的数据库

    ASNTDIFF的diff table有一列类型为varchar 15000,z上创建db默认的pagesize是4K,无法创建table,所以需要创建一个大pagesize的database. db ...

  2. NYOJ题目766回文数

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAsgAAAHaCAIAAACSPygsAAAgAElEQVR4nO3dO3LqSheG4X8S5AyEWB ...

  3. Linux snmp

    http://www.cnblogs.com/amberly/p/4364072.html http://blog.csdn.net/awenluck/article/details/50220221

  4. DedeCMS Error: (PHP 5.3 and above) Please set request_order

    部分使用PHP 5.3的主机可能会有下面的提示: (PHP 5.3 and above) Please set 'request_order' ini value to include C,G and ...

  5. 【转载】 Python 方法参数 * 和 **

    Python的函数定义中有两种特殊的情况,即出现*,**的形式. 如:def myfun1(username, *keys)或def myfun2(username, **keys)等. 他们与函数有 ...

  6. SQL在INNER JOIN时,也可以将子查询加入进来

    这个语法有点神奇,记下. 但觉得用处有限吧. mysql> SELECT a.account_id, a_cust_id, a.open_date, a.product_cd -> FRO ...

  7. 攻城狮在路上(壹) Hibernate(十)--- 映射值类型集合

    一.映射Set(集):未排序,无重复. 实例代码: <set name="images" table="IMAGES" lazy="true&q ...

  8. Visual Studio Code升级到0.5,提供对ES6的更好支持

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:题目即题记. 自从Visual Studio Code发布之后(最初是0.1),微软就 ...

  9. FreeSWITCH 体系配置结构

    转自:http://www.cnblogs.com/logo-fox/archive/2013/12/09/3465440.html FreeSWITCH总体结构: FreeSWITCH 由一个稳定的 ...

  10. 第二十一篇:SOUI中的控件注册机制

    Win32编程中,用户需要一个新控件时,需要向系统注册一个新的控件类型.注册以后,调用::CreateWindow时才能根据标识控件类型的字符串创建出一个新的控件窗口对象. 为了能够从XML描述的字符 ...