将分组计划按照$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. 手写代码自动实现自动布局,即Auto Layout的使用

    手写代码自动实现自动布局,即Auto Layout的使用,有需要的朋友可以参考下. 这里要注意几点: 对子视图的约束,若是基于父视图,要通过父视图去添加约束. 对子视图进行自动布局调整,首先对UIVi ...

  2. Java观察者模式(Observer模式)

    Java深入到一定程度,就不可避免的碰到设计模式(design pattern)这一概念,了解设计模式,将使自己对java中的接口或抽象类应用有更深的理解.设计模式在java的中型系统中应用广泛,遵循 ...

  3. 2014年十个优秀的免费CDN加速服务-国内和国外免费CDN

    这是一篇总结近几年来网络上出现了各类免费CDN服务的文章,文章本来应该早就发出来的,但是因为近期的各种原因一直拖到现在.之前部落已经总结了近几年来的优秀免费空间,新手朋友不必在茫茫“网”海中寻找免费空 ...

  4. JavaScript基础——使用JavaScript对象

    JavaScript有许多内置对象,如Number(数字).Array(数组).String(字符串).Date(日期)和Math(数学).这些内置对象都有成员属性和方法.除了JavaScript对象 ...

  5. EF – 1.模式

      3种数据库 code first model first database first       创建EF http://www.cnblogs.com/tangge/p/3834578.htm ...

  6. SSIS Dataflow使用存储过程不能检索列名

    在项目中遇到一个问题,需要在Dataflow中调用一个存储过程,然后把结果生成一个csv文件. 然而在dataflow调用存储过程中遇到了问题,SP不能正确的返回列名. 在SSMT里面明明是可以查出数 ...

  7. HDU5489 Removed Interval(动态规划)

    一个长度为n的序列,删除任意长度为l的连续子序列后,求剩下的序列的最长公共子序列. 先求出以第i个元素为开始的LIS的长度,再一次循环,对所要求的结果更新 #include<iostream&g ...

  8. .NET NLog 详解(一)

    安装NLog NLog 的源代码托管在Github 上,一般的人直接使用NuGet就可以了. 这里我们选择安装NLog.Config.当然最方便的还是直接使用命令行: Install-Package ...

  9. android 入门-R文件的死与活

    1.图片的名字Btn_Play R文件死了. 1.答:修改图片的名字btn_play R文件活了.

  10. W:Failed to fetch http://archive.ubuntukylin.com:10006/ubuntukylin/dists/pre

    由于用ubuntu的时候装了几个ubuntukylin的软件(像搜狗拼音for linux),于是最近总是蹦出一个红色的三角提示,说无法更新,虽说不影响使用但是还是很不爽.解决方法记录如下: 进入系统 ...