徐州网络赛 G Trace (思维题+set集合性质)

题目链接:https://nanti.jisuanke.com/t/31459

#include<bits/stdc++.h>
#pragma comment(linker,"/STACK:1024000000,1024000000")
using namespace std;

#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define read(x,y) scanf("%d%d",&x,&y)

#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define ll long long
const int  maxn =1e6+5;
const int mod=1e9+7;
ll powmod(ll x,ll y) {ll t;for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod;return t;}
ll gcd(ll x,ll y)  {  return y==0?x:gcd(y,x%y); }

set<int> sx,sy;///维护横纵轴坐标
set<int>:: iterator it;
int x[maxn],y[maxn],n;///集合
/*
题目大意:几何矩形覆盖问题,
跟时间序列有关的覆盖。

技巧思维题:
这类题目有些特征,
就是前面的答案可能会受到后面答案的影响,
所以要倒叙思考。
据题目,最后一个插入的矩形肯定是
全部保留下来的。
不妨维护一个x轴和y轴集合,
然后每次插入的x,y线段,
可以看成是一系列有时间顺序的长度序列,
时间倒过来后,新加的序列线段一定是亏损过的,
手动模拟后,不难发现
(注意题目中要求没有两个完全覆盖的关系的矩形,这很关键~)
新加的矩形一定至少要相交一条边,并且是在阶梯的拐角上加边,
即每次肯定都是形成新的阶梯状,
这样对于每次加入的边,
模拟中只要找到最后一个比其小的边做差,答案贡献个差值即可。

*/

int main()
{
    scanf("%d",&n);   for(int i=0;i<n;i++)   scanf("%d%d",&x[i],&y[i]);
    sx.clear();sy.clear();
    ll ans=0;
    for(int i=n-1;i>=0;i--)
    {
        it=sx.lower_bound(x[i]);
        if(it==sx.begin() || sx.empty() ) ans+=x[i];
        else ans+=(x[i]-*(--it));

        it=sy.lower_bound(y[i]);
        if(it==sy.begin() || sy.empty() ) ans+=y[i];
        else ans+=(y[i]-*(--it));
        sx.insert(x[i]);
        sy.insert(y[i]);
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37451344/article/details/82623814