bzoj千题计划155:bzoj3543: [ONTAK2010]Garden

http://www.lydsy.com/JudgeOnline/problem.php?id=3543

枚举每一个点,作为左下角

然后枚举 相同的x坐标,y坐标 少的那个 作为另一个角

二分判断另外两个角是否存在

#include<map>
#include<vector>
#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;

#define N 100001

int x[N],y[N];
int hx[N],hy[N],tx,ty;

map<int,int>fx,fy;

vector<int>sx[N],sy[N];

void read(int &x)
{
    x=0; int f=1; char c=getchar();
    while(!isdigit(c)) { if(c==‘-‘) f=-1; c=getchar(); }
    while(isdigit(c)) { x=x*10+c-‘0‘; c=getchar(); }
    x*=f;
}

int main()
{
    int n;
    read(n);
    int mi=0;
    for(int i=1;i<=n;++i)
    {
        read(x[i]);
        read(y[i]);
        hx[++tx]=x[i];
        hy[++ty]=y[i];
        mi=min(mi,x[i]);
        mi=min(mi,y[i]);
    }
    sort(hx+1,hx+tx+1);
    sort(hy+1,hy+ty+1);
    tx=unique(hx+1,hx+tx+1)-hx-1;
    ty=unique(hy+1,hy+ty+1)-hy-1;
    for(int i=1;i<=n;++i)
    {
        x[i]=lower_bound(hx+1,hx+tx+1,x[i])-hx;
        y[i]=lower_bound(hy+1,hy+ty+1,y[i])-hy;
    }
    mi=max(0,-mi);
    for(int i=1;i<=tx;++i) fx[hx[i]+mi]=i;
    for(int i=1;i<=ty;++i) fy[hy[i]+mi]=i;
    for(int i=1;i<=n;++i)
    {
        sx[x[i]].push_back(y[i]);
        sy[y[i]].push_back(x[i]);
    }
    for(int i=1;i<=tx;++i) sort(sx[i].begin(),sx[i].end());
    for(int i=1;i<=ty;++i) sort(sy[i].begin(),sy[i].end());
    int j,k;
    int sizx,sizy;
    int len;
    int xx,yy;
    int ans=0;
    for(int i=1;i<=n;++i)
    {
        j=upper_bound(sx[x[i]].begin(),sx[x[i]].end(),y[i])-sx[x[i]].begin();
        k=upper_bound(sy[y[i]].begin(),sy[y[i]].end(),x[i])-sy[y[i]].begin();
        sizx=sx[x[i]].size();
        sizy=sy[y[i]].size();
        if(sizx-j<sizy-k)
        {
            for(;j<sizx;++j)
            {
                len=hy[sx[x[i]][j]]-hy[y[i]];
                xx=fx[hx[x[i]]+len+mi];
                if(!xx) continue;
                if(binary_search(sx[xx].begin(),sx[xx].end(),y[i]) && binary_search(sx[xx].begin(),sx[xx].end(),sx[x[i]][j]))
                    ans++;
            }
        }
        else
        {
            for(;k<sizy;++k)
            {
                len=hx[sy[y[i]][k]]-hx[x[i]];
                yy=fy[hy[y[i]]+len+mi];
                if(!yy) continue;
                if(binary_search(sy[yy].begin(),sy[yy].end(),x[i]) && binary_search(sy[yy].begin(),sy[yy].end(),sy[y[i]][k]))
                    ans++;
            }
        }
    }
    cout<<ans;
}
时间: 2024-10-28 08:53:00

bzoj千题计划155:bzoj3543: [ONTAK2010]Garden的相关文章

bzoj千题计划185:bzoj1260: [CQOI2007]涂色paint

http://www.lydsy.com/JudgeOnline/problem.php?id=1260 区间DP模型 dp[l][r] 表示涂完区间[l,r]所需的最少次数 从小到大们枚举区间[l,r] 如果col[l]==col[r] dp[l][r]=min(dp[l+1][r],dp[l][r-1],dp[l+1][r-1]+1) 否则 dp[l][r]=min(dp[l][k]+dp[k+1][r]) 我还是辣鸡啊~~~~(>_<)~~~~,这种题都不能秒 #include<c

bzoj千题计划292:bzoj2244: [SDOI2011]拦截导弹

http://www.lydsy.com/JudgeOnline/problem.php?id=2244 每枚导弹成功拦截的概率 = 包含它的最长上升子序列个数/最长上升子序列总个数 pre_len [i] 表示以i结尾的最长不下降子序列的长度 pre_sum[i] 表示对应长度下的方案数 suf_len[i] 表示以i开头的最长不下降子序列长度 suf_sum[i] 表示对应长度下的方案数 若已有了这4个数组 设最长上升子序列长度=mx 那么 如果pre_len[i]+suf_len[i] -

bzoj千题计划304:bzoj3676: [Apio2014]回文串

https://www.lydsy.com/JudgeOnline/problem.php?id=3676 回文自动机模板题 4年前的APIO如今竟沦为模板,,,╮(╯▽╰)╭,唉 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 300001 char ss[N]; int s[N]; int tot=1,last; int fail[N],len

bzoj千题计划106:bzoj1014 [JSOI2008]火星人prefix

http://www.lydsy.com/JudgeOnline/problem.php?id=1014 两个后缀的最长公共前缀:二分+hash 带修改带插入:splay维护 #include<cstdio> #include<cstring> #include<iostream> #define L 100001 typedef unsigned long long ULL; using namespace std; char s[L+4]; int tot,root

bzoj千题计划108:bzoj1018: [SHOI2008]堵塞的交通traffic

http://www.lydsy.com/JudgeOnline/problem.php?id=1018 关键点在于只有两行 所以一个2*m矩形连通情况只有6种 编号即对应代码中的a数组 线段树维护 用b数组表示 节点第0/1行的最右一列是否连接了右边 来 辅助 节点的合并 查询 对两个点位于矩形的位置分4种情况讨论 两点是否联通,要考虑四种情况 (以两个位置是矩形左上角和右上角为例) 1.直接联通,线段树的节点包含了这种情况,直接判断 2. 3. 4. 后三种情况需要再查询[1,l]和[r,n

bzoj千题计划109:bzoj1019: [SHOI2008]汉诺塔

http://www.lydsy.com/JudgeOnline/problem.php?id=1019 题目中问步骤数,没说最少 可以大胆猜测移动方案唯一 (真的是唯一但不会证) 设f[i][j] 表示 从i号柱子 上把j个盘子移到 g[i][j] 柱子上的步数 初始化:f[0][1]=1,g[0][1] 根据优先级决定 设三根柱子分别为0,1,2 对于每一个f[x][i], 把前i-1个移走,把第i个移走,把前i-1个移回 令y=g[x][i-1],则k=0+1+2-x-y 我们希望 把i-

bzoj千题计划111:bzoj1021: [SHOI2008]Debt 循环的债务

http://www.lydsy.com/JudgeOnline/problem.php?id=1021 如果A收到了B的1张10元,那么A绝对不会把这张10元再给C 因为这样不如B直接给C优 由此可以推出 若A欠B20元,B欠C 30元, 那么A还C20元,B还C10元最优 所以一共只有 A->BC   B->AC  C->AB AB->C  BC->A  AC->B 这6种转移情况 根据输入,我们可以知道三人最终手中有多少钱ea.eb.ec,一共有多少钱sum 设f

bzoj千题计划112:bzoj1022: [SHOI2008]小约翰的游戏John

http://www.lydsy.com/JudgeOnline/problem.php?id=1022 http://www.cnblogs.com/TheRoadToTheGold/p/6744825.html #include<cstdio> #include<iostream> using namespace std; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar();

bzoj千题计划113:bzoj1023: [SHOI2008]cactus仙人掌图

http://www.lydsy.com/JudgeOnline/problem.php?id=1023 dp[x] 表示以x为端点的最长链 子节点与x不在同一个环上,那就是两条最长半链长度 子节点与x在同一个环上,环形DP,单调队列优化 对于每一个环,深度最小的那个点 有可能会更新 上层节点, 所以 每一个环DP完之后,更新 dp[深度最小的点] #include<cstdio> #include<iostream> #include<algorithm> using