bzoj 1824: [JSOI2010]下棋问题

考虑每次新放一个棋子会产生多少新的矩形,以及减掉多少旧的矩形。

用第$i$个点的坐标把坐标轴分成4个象限。

显然第一问的答案用四个单调栈就能解决。

而且第二问每个矩形的两个端点一定在1,3或2,4象限的单调栈里。

枚举第一象限里的一个点,剩下三个象限里维护3个指针,就能找出来第3象限里能和当前点组成矩形的点。

二四象限同理。

#include<bits/stdc++.h>
#define N 5005
#define ll long long
using namespace std;
int n;
struct node
{
    int x,y;
}a[N];
ll ans1,ans2,now;
int p[N];
bool cmp(int x,int y)
{
    return a[x].x<a[y].x;
}
int q1[N],q2[N],q3[N],q4[N],top[5];
int solve(int x)
{
    memset(top,0,sizeof(top));
    for(int i=1;i<=n;i++)
    {
        if(p[i]<x)
        {
            int op=1;
            int t=p[i];
            if(a[t].x<a[x].x&&a[t].y>a[x].y)op=2;
            if(a[t].x<a[x].x&&a[t].y<a[x].y)op=3;
            if(a[t].x>a[x].x&&a[t].y<a[x].y)op=4;
            if(op==1)if(!top[1]||a[t].y<a[q1[top[1]]].y)q1[++top[1]]=t;

            if(op==2)
            {
                while(top[2]&&a[t].y<a[q2[top[2]]].y)top[2]--;
                q2[++top[2]]=t;
            }

            if(op==3)
            {
                while(top[3]&&a[t].y>a[q3[top[3]]].y)top[3]--;
                q3[++top[3]]=t;
            }

            if(op==4)if(!top[4]||a[t].y>a[q4[top[4]]].y)q4[++top[4]]=t;
        }
    }
    int ans=top[1]+top[2]+top[3]+top[4];
    int p1=top[2],p2=0,p3=top[3]+1,p4=top[3];
    for(int i=1;i<=top[1];i++)
    {
        while(p1>=1&&a[q2[p1]].y>a[q1[i]].y)p1--;

        while(p2+1<=top[4]&&a[q4[p2+1]].x<a[q1[i]].x)p2++;

        while(p3-1>=1&&(!p1||a[q3[p3-1]].x>a[q2[p1]].x))p3--;

        while(p4>=1&&(p2!=0&&a[q4[p2]].y>a[q3[p4]].y))p4--;

        if(p4>=p3)ans-=p4-p3+1;
    }

    p1=top[1]+1,p2=0,p3=top[4]+1,p4=top[4];
    for(int i=1;i<=top[2];i++)
    {
        while(p1-1>=1&&a[q1[p1-1]].y<a[q2[i]].y)p1--;

        while(p2<=top[3]&&a[q3[p2]].x<a[q2[i]].x)p2++;

        while(p3-1>=1&&(p2==top[3]+1||a[q4[p3-1]].y>a[q3[p2]].y))p3--;

        while(p4>=1&&(p1!=top[1]+1&&a[q4[p4]].x>a[q1[p1]].x))p4--;

        if(p4>=p3)ans-=p4-p3+1;
    }

    return ans;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y);
    for(int i=1;i<=n;i++)p[i]=i;
    sort(p+1,p+n+1,cmp);
    for(int i=1;i<=n;i++)
    {
        now+=solve(i);
        if(i&1)ans1+=now;
        else ans2+=now;
    }
    printf("%lld %lld\n",ans1,ans2);
    return 0;
}

  

时间: 2024-10-16 05:29:16

bzoj 1824: [JSOI2010]下棋问题的相关文章

bzoj 1822: [JSOI2010]Frozen Nova 冷冻波 题解

[原题] 1822: [JSOI2010]Frozen Nova 冷冻波 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 796  Solved: 218 [Submit][Status] Description WJJ喜欢"魔兽争霸"这个游戏.在游戏中,巫妖是一种强大的英雄,它的技能Frozen Nova每次可以杀死一个小精灵.我们认为,巫妖和小精灵都可以看成是平面上的点. 当巫妖和小精灵之间的直线距离不超过R,且巫妖看到小精灵的视线没

BZOJ 1823: [JSOI2010]满汉全席( 2-sat )

2-sat...假如一个评委喜好的2样中..其中一样没做, 那另一样就一定要做, 这样去建图..然后跑tarjan. 时间复杂度O((n+m)*K) ---------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<stack> using na

BZOJ 2208: [Jsoi2010]连通数( DFS )

n只有2000,直接DFS就可以过了... -------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cctype> #define rep( i, n ) for( int i = 0; i

bzoj 2208: [Jsoi2010]连通数

一看就是缩点拓扑啊,可数据范围这么小,暴力即可啊. 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<queue> 7 #include<algorithm> 8 #include<vector> 9 #define M 1000009 10 #

BZOJ 1821 [JSOI2010] Group 部落划分 Group

最小生成森林? 个人感觉跟最小生成树差不多.需要分成k个联通块,让联通块之间距离最大就让联通块内距离尽可能小.一颗最小生成树是N-1条边,分成k个块需要切k-1条,就是一个n-k条边的最小生成森林,然后Kruskal中的下一条边(第n-k+2条)就是答案了. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> #incl

BZOJ 1821 JSOI2010 部落划分 Group Kruskal

题目大意:给定平面上的n个点,要求将这n个点划分为k个集合,使划分后任意两个集合中最近两点的距离的最大值最小,输出这个最小值 考虑这n个点之间所有的连边 我们要让长边保留 就尽量选取短边链接 于是就是求加入n-k条边的最小生成森林 由于输出下一个最小值 因此Kruskal加入第n-k+1条边时输出边权即可 #include <cmath> #include <cstdio> #include <cstring> #include <iomanip> #inc

[BZOJ 1823][JSOI2010]满汉全席(2-SAT)

Description 满汉全席是中国最丰盛的宴客菜肴,有许多种不同的材料透过满族或是汉族的料理方式,呈现在數量繁多的菜色之中.由于菜色众多而繁杂,只有极少數博学多闻技艺高超的厨师能够做出满汉全席,而能够烹饪出经过专家认证的满汉全席,也是中国厨师最大的荣誉之一. 世界满汉全席协会是由能够料理满汉全席的专家厨师们所组成,而他们之间还细分为许多不同等级的厨师.为了招收新进的厨师进入世界满汉全席协会,将于近日举办满汉全席大赛,协会派遣许多会员当作评审员,为的就是要在參赛的厨师之中,找到满汉料理界的明日

BZOJ 1821 [JSOI2010]Group 部落划分:MST

Description 聪聪研究发现,荒岛野人总是过着群居的生活,但是,并不是整个荒岛上的所有野人都属于同一个部落,野人们总是拉帮结派形成属于自己的部落,不同的部落之间则经常发生争斗.只是,这一切都成为谜团了——聪聪根本就不知道部落究竟是如何分布的. 不过好消息是,聪聪得到了一份荒岛的地图.地图上标注了N个野人居住的地点(可以看作是平面上的坐标).我们知道,同一个部落的野人总是生活在附近.我们把两个部落的距离,定义为部落中距离最近的那两个居住点的距离.聪聪还获得了一个有意义的信息——这些野人总共

bzoj 1823: [JSOI2010]满汉全席

1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 int t,n,m,head[205],next[2005],v[2005],cnt,dfn[205],cnt1,low[205]; 6 int zhan[205],zhan1[205],top,shu[205],shu1; 7 int du() 8 { 9 int a1; 10 char ch; 11