将分组计划按照$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. mysql 三个表连接查询

    权限表(permission)10 字段名称 类型 约束 描述 authorityid integer Pk not null 权限流水号id    PK userNameId int not nul ...

  2. JQ 全选设定与设置选中

    复选数据框 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w ...

  3. Redis笔记(七)Java实现Redis消息队列

    这里我使用Redis的发布.订阅功能实现简单的消息队列,基本的命令有publish.subscribe等. 在Jedis中,有对应的java方法,但是只能发布字符串消息.为了传输对象,需要将对象进行序 ...

  4. Java内存泄露的理解与解决

    依赖于引用判断的内存管理机制 Java中对内存对象的访问,使用的是引用的方式.在Java代码中我们维护一个内存对象的引用变量,通过这个引用变量的值,我们可以访问到对应的内存地址中的内存对象空间.在Ja ...

  5. 设计模式学习之适配器模式(Adapter,结构型模式)(14)

    参考链接:http://www.cnblogs.com/zhili/p/AdapterPattern.html一.定义:将一个类的接口转换成客户希望的另一个接口.Adapter模式使得原本由于接口不兼 ...

  6. Android 下拉刷新

    以前旧版用的是开源的PullToRefresh第三方库,该库现在已经不再维护了: chrisbanes/Android-PullToRefreshhttps://github.com/chrisban ...

  7. 恢复 git reset -hard 的误操作

    有时候使用Git工作得小心翼翼,特别是涉及到一些高级操作,例如 reset, rebase 和 merge.甚至一些很小的操作,例如删除一个分支,我都担心数据丢失. 不 久之前,我在做一些大动作(re ...

  8. 第十八篇:在SOUI中实现PreTranslateMessage

    在MFC中,通常可以通过重载CWnd::PreTranslateMessage这样一个虚函数来实现对一些窗口消息的预处理.多用于tooltip的显示控制. 在SOUI中也实现了类似的机制. 要在SOU ...

  9. [unity3d插件]2dtoolkit系列一 创建精灵

    从今天开始要做一个2d游戏,由于之前都是做cocos2dx的,然后接触了一段时间的unity3d,都是做3D方面的东西,得知要做2d游戏还是有点开心的,或许因为不想丢失之前的2d游戏的一些思想,然后接 ...

  10. the last lecture

    2008.07.25,CMU教授Randy Pausch教授因癌症去世,仅47岁. 几年之前,当我看到Pausch先生最后一课的视频时,让我震撼. 转眼之间,7年过去了,这7年,让我成长了许多. 7年 ...