D:NLO(除草 set维护线段)

原题: http://acm.zjnu.edu.cn/CLanguage/contests/1146/problems/1003.html

题意:

一个 n m n*m 的矩阵,初始全部为0。k秒钟,每秒一个 x , y , r x,y,r ,将符合 ( x X ) 2 + ( y Y ) 2 < = r 2 (x-X)^2+(y-Y)^2<=r^2 的所有点值变成0,不符合的点值加1。问k秒后所有点的值之和。

解析:

从后往前维护,第k秒的区间变成0,第k-1秒的区间除了已经被包含的区间以外变成1,依次类推。将一个区间分成多条线,用set维护一下这个线即可。

麻烦的地方在这是一个圆,需要计算每条线的起点和长度就变得比较麻烦。

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i,a,b) for(register int i=a;i<=b;i++)
#define debug(i) printf("->%d\n",i)

const int maxn=109,maxm=2e5+5;
int x[maxn],y[maxn],r[maxn];
struct node{
    int y1,y2;
    node(){}
    node(int y1,int y2):y1(y1),y2(y2){}
    bool operator<(const node &r)const{
        return y2<r.y2;
    }
};
set<node>S[maxm];
LL ans=0;

node tmp;
void Push(int val,int idx,int y1,int y2){
    tmp.y2=y1;
    set<node>::iterator it=S[idx].lower_bound(tmp);
    set<node>::iterator tmp=it;

    if(it==S[idx].end() || (*it).y1>y2){
        S[idx].insert(node(y1,y2));
        ans-=(LL)val*(LL)(y2-y1+1);
        return;
    }

    int l=min(y1,(*it).y1),r=y2;
    int old=0;
    int needcut=0;
    while(it!=S[idx].end() && (*it).y1<=y2){
        r=max(r,(*it).y2);
        old+=(*it).y2-(*it).y1+1;
        needcut++;
        it++;
    }
    ans-=(LL)val*(LL)(r-l+1-old);
    while(needcut--){
        S[idx].erase(tmp++);
    }
    S[idx].insert(node(l,r));
}
inline judge(int x,int y,int x0,int y0,int r0){
    return (x-x0)*(x-x0)+(y-y0)*(y-y0)<=r0*r0;
}
int main(){
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    ans=(LL)n*(LL)m*(LL)k;
    for(int i=1;i<=k;i++){
        scanf("%d%d%d",x+i,y+i,r+i);
    }
    int idx,y1,y2,X,Y;
    for(int i=k;i>=1;i--){
        X=x[i],Y=y[i]-r[i];
        while(1){
            idx=X+Y,y1=Y,y2=y[i]+(X-x[i]);
            Push(i,idx,y1,y2);
            if(X!=x[i]&&!judge(X-1,Y-1,x[i],y[i],r[i])){
                int toX=2*x[i]-X,toY=Y;
                idx=toX+toY;
                y1=toY,y2=y[i]+(toX-x[i]);
                Push(i,idx,y1,y2);
            }
            if(Y!=y[i]&&!judge(X+1,Y+1,x[i],y[i],r[i])){
                int toX=X,toY=2*y[i]-Y;
                idx=toX+toY;
                y1=toY,y2=y[i]+(toX-x[i]);
                Push(i,idx,y1,y2);
            }
            if(X==x[i]+r[i]&&Y==y[i])break;
            if(judge(X+1,Y,x[i],y[i],r[i])){
                X++;
            }
            else{
                Y++;
            }
        }
    }
    printf("%lld\n",ans);
}

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/88780117