【PA2011】Kangaroos

原创 2016年04月24日 08:52:06

Description

定义两个区间互相匹配表示这两个区间有交集。

给出长度为N的区间序列A,M次询问,每次询问序列A中最长的连续子序列,使得子序列中的每个区间都与[L,R]互相匹配
N<=50000,M<=200000
Input

Output

Sample Input

3 3

2 5

1 3

6 6

3 5

1 10

7 9
Sample Output

2

3

0
HINT

Source

从Claris permu那题的题解可以拿来给这个题用,发现完全一样
考虑把一个区间[L,R]当成(L,R)
然后把询问点插入进kdtree,可以发现kdtree的一个点,对他有贡献的区域是他右下方的矩形
然后把n个序列点按顺序逐个插入进去,可以发现他贡献出答案的点是这n个点左上方的.对左上方的贡献是+1,其他点则是清零
可以对m个询问点维护以下信息:历史点最大序列长,历史矩阵最大序列长,历史点最大清零时间,历史矩阵最大清零时间,最小清零时间
显然可以用当前时间和之前的清零时间算一算算出一个序列长度
就这样标记打一打就行了
但是标记打起来非常麻烦..参考了鸟神的题解..

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 200010
#define Dnum 2
#define GET (ch>='0'&&ch<='9')
using namespace std;
inline void in(int &x)
{
    char ch=getchar();x=0;
    while (!GET)    ch=getchar();
    while (GET) x=x*10+ch-'0',ch=getchar();
}
int n,m,root;
bool cmp_d;
int id[MAXN],x[MAXN],y[MAXN];
struct KDtree
{
    int ch[2],f,d[Dnum],minn[Dnum],maxn[Dnum],maxv[Dnum],maxt[Dnum],mint;
    inline void init()  {   for (int i=0;i<Dnum;++i)    minn[i]=maxn[i]=d[i],maxv[i]=maxt[i]=0; }
    inline bool operator < (const KDtree& a)const   {   return d[cmp_d]<a.d[cmp_d]; }
}tree[MAXN];
inline void add(int rt,int x,int y)
{
    if (~x)
    {
        if (~tree[rt].mint)    tree[rt].maxv[0]=max(tree[rt].maxv[0],x-tree[rt].maxt[0]-1);
        else    tree[rt].mint=x;
        tree[rt].maxv[1]=max(tree[rt].maxv[1],x-tree[rt].maxt[1]-1);
        tree[rt].maxt[0]=tree[rt].maxt[1]=y;
    }
}
inline void push_up(int rt)
{
    for (int x=0,i=0;i<2;++i)
        if ((x=tree[rt].ch[i]))
            for (int j=0;j<Dnum;++j)
                tree[rt].minn[j]=min(tree[rt].minn[j],tree[x].minn[j]),
                tree[rt].maxn[j]=max(tree[rt].maxn[j],tree[x].maxn[j]);
}
inline void push_down(int rt)
{
    int x=tree[rt].mint,y=tree[rt].maxt[0];
    for (int i=0,j=0;i<2;++i)   if ((j=tree[rt].ch[i])) add(j,x,y);
    tree[rt].mint=-1;
}
int rebuild(int l=1,int r=m,bool d=0,int f=0)
{
    cmp_d=d;int mid=(l+r)>>1;nth_element(tree+l,tree+mid,tree+r+1);
    id[tree[mid].f]=mid;tree[mid].f=f;tree[mid].init();
    if (l!=mid) tree[mid].ch[0]=rebuild(l,mid-1,d^1,mid);
    if (r!=mid) tree[mid].ch[1]=rebuild(mid+1,r,d^1,mid);
    return push_up(mid),mid;
}
inline int check(int x1,int y1,int x2,int y2,int x,int y)
{
    int ret=0;
    ret+=(x1<=x&&y1>=y);ret+=(x1<=x&&y2>=y);ret+=(x2<=x&&y1>=y);ret+=(x2<=x&&y2>=y);
    return ret?(ret==4?1:2):0;
}
void modify(int rt,int x,int y,int id)
{
    int flag=check(tree[rt].minn[0],tree[rt].minn[1],tree[rt].maxn[0],tree[rt].maxn[1],x,y);
    if (!flag)  {   add(rt,id,id);return;   }
    if (flag==1)    return;
    if (tree[rt].d[0]>x||tree[rt].d[1]<y)   tree[rt].maxv[1]=max(tree[rt].maxv[1],id-tree[rt].maxt[1]-1),tree[rt].maxt[1]=id;
    push_down(rt);
    for (int i=0;i<2;++i)   if (tree[rt].ch[i]) modify(tree[rt].ch[i],x,y,id);
}
void update(int rt,int x)
{
    push_down(rt);
    tree[rt].maxv[1]=max(tree[rt].maxv[1],n-tree[rt].maxt[1]);
    tree[rt].maxv[1]=max(tree[rt].maxv[1],x);
    tree[rt].maxv[0]=max(tree[rt].maxv[0],x);
    tree[rt].maxv[1]=max(tree[rt].maxv[1],tree[rt].maxv[0]);
    for (int i=0;i<2;++i)   if (tree[rt].ch[i]) update(tree[rt].ch[i],tree[rt].maxv[0]);
}
int main()
{
    in(n);in(m);
    for (int i=1;i<=n;++i)  in(y[i]),in(x[i]);
    for (int i=1;i<=m;++i)  in(tree[i].d[0]),in(tree[i].d[1]),tree[i].f=i;
    root=rebuild();
    for (int i=1;i<=n;++i)  modify(root,x[i],y[i],i);
    update(root,0);
    for (int i=1;i<=m;++i)  printf("%d\n",tree[id[i]].maxv[1]);
}
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/CreationAugust/article/details/51231976

3073: [Pa2011]Journeys|线段树|BFS

一种比较暴力的方法就是直接线段树优化建图,跑dijkstradijkstra 但是这题的边权都是11可以考虑BFS的方法 首先按照yy将所有的边排序,然后按照xx的大小插入到线段树中 这样每次询...
  • ws_yzy
  • ws_yzy
  • 2016年04月18日 15:30
  • 730

【BZOJ】4130: [PA2011]Kangaroos【KD树——最长连续1的子段长度】

传送门:【BZOJ】4130: [PA2011]Kangaroos【KD树】题意:给出一个长度为N(N≤5⋅104)N(N\leq 5\cdot 10^4)的区间序列。然后接下来M(M≤2⋅105)M...
  • u013368721
  • u013368721
  • 2015年11月12日 19:45
  • 932

【PA2011】Kangaroos

Description定义两个区间互相匹配表示这两个区间有交集。给出长度为N的区间序列A,M次询问,每次询问序列A中最长的连续子序列,使得子序列中的每个区间都与[L,R]互相匹配 N...
  • CreationAugust
  • CreationAugust
  • 2016年04月24日 08:52
  • 879

PA_v4.2.6_windows

  • 2010年03月26日 14:24
  • 2.53MB
  • 下载

CodeForces 372A Counting Kangaroos is Fun 动物PK

原题: http://codeforces.com/problemset/problem/372/A题目大意: 找到尽可能多的两满足a*2...
  • qq_27508477
  • qq_27508477
  • 2015年07月29日 18:30
  • 641

【PA2011】【BZOJ3073】Journeys

DescriptionSeter建造了一个很大的星球,他准备建造N个国家和无数双向道路。N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条建简直是不可能的!于是他以如下方式建造...
  • CreationAugust
  • CreationAugust
  • 2016年02月25日 17:08
  • 976

BZOJ3073 [Pa2011]Journeys

一眼线段树优化建图01bfs 考虑一下怎么优化 搞两棵线段树,线段树上的边都是0,对于一次新建一个单向边(题里建的是双向边,拆成俩单向边即可),新建两个点,两个点之间连一个边权为1的,然后第一颗线...
  • neither_nor
  • neither_nor
  • 2017年03月29日 14:55
  • 182

【PA2011】【BZOJ3069】Hard Choice 艰难的选择

DescriptionByteasar是一个很纠结的人。每次他经过Bytetown的时候都知道有至少2条不同的路径可以选择,这导致他必须花很长时间来决定走哪条路。Byteasar最近听说了Byteto...
  • CreationAugust
  • CreationAugust
  • 2016年02月29日 11:47
  • 1049

BZOJ3069: [Pa2011]Hard Choice 艰难的选择

很好的一道LCT的题目 虽然能马上发现时LCT但是这个性质起码我是画了个图。。。 要处在同一个强联通分量里的点才有两条不重合路径 那么很容易想出来只需要离线每次加边同时缩点就好了 然后只需要打...
  • liutian429073576
  • liutian429073576
  • 2016年03月04日 15:21
  • 568

BZOJ3069 [Pa2011]Hard Choice 艰难的选择

删边不好做,我们考虑倒着来,这样变成加边 先随便搞个生成树,为了方便不妨按删除时间做最大生成树,这样能保证先加入的一定是父子边,后加入的是非树边 那么一次原来的删边操作就相当于把树上一条链上的点都...
  • neither_nor
  • neither_nor
  • 2017年04月01日 11:31
  • 385
收藏助手
不良信息举报
您举报文章:【PA2011】Kangaroos
举报原因:
原因补充:

(最多只允许输入30个字)