zoukankan      html  css  js  c++  java
  • 19南京网络赛A 扫描线

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

    扫描线的简单题,题目难在找宫殿的价值(°ー°〃),比赛时将近100多行代码找价值,纯模拟,看到题解哭了。

    存下每个宫殿的横坐标、价值,存下每个矩形平行于y轴的两条边,左边的那个边要特殊处理,就是横坐标减一。线段树维护y坐标区间和。坐标离散化处理,按x遍历线段,先线段树更新点在y坐标上的值,再处理边,如果线段是矩形终止的边,答案即为更新完点之后查询线段树[y1,y2]上的区间和再减去起始边时查询线段树[y1,y2]上的区间和。

    #include<iostream>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define ls l,mid,rt<<1
    #define rs mid+1,r,rt<<1|1
    #define maxn 2000005
    ll n,m,p,sum[maxn<<2],lazy[maxn<<2],ans[maxn];
    int ly[maxn];
    struct node{
        int x,y,val;
        bool operator <(const node &w)const{
            return x<w.x;
        }
    }a[maxn];
    struct seg{
        int x,l,r,s,id;
        seg(){}
        seg(int x,int l,int r,int s,int id):x(x),l(l),r(r),s(s),id(id){};
        bool operator <(const seg &w)const{
            if(x==w.x)return s<w.s;
            return x<w.x;
        }
    }se[maxn<<1];
    int getval(int x,int y)
    {
        ll num,t;
        x=x-n/2-1;y=y-n/2-1;
        t=max(abs(x),abs(y));
        if(x>=y)num=1ll*n*n-4*t*t-2*t-x-y;
        else num=1ll*n*n-4*t*t+2*t+x+y;
        int ret=0;
        while(num)
        {
            ret+=num%10;
            num/=10;
        }
        return ret;
    }
    void build(int l,int r,int rt)
    {
        sum[rt]=lazy[rt]=0;
        if(l==r)return ;
        int mid=l+r>>1;
        build(ls);build(rs);
        sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    }
    void update(int p,int val,int l,int r,int rt)
    {
        if(l==r)
        {
            sum[rt]+=val;return ;
        }
        int mid=l+r>>1;
        if(p<=mid)update(p,val,ls);
        else update(p,val,rs);
        sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    }
    ll query(int L,int R,int l,int r,int rt)
    {
        if(L<=l&&R>=r)return sum[rt];
        int mid=l+r>>1;
        ll ret=0;
        if(L<=mid)ret+=query(L,R,ls);
        if(R>mid)ret+=query(L,R,rs);
        return ret;
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%lld%lld%lld",&n,&m,&p);
            int x,y,x1,y1,val,tot=0,cnt=0;
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d",&x,&y);
                val=getval(x,y);
                a[++tot].x=x;a[tot].y=y;a[tot].val=val;
                ly[tot]=y;
            }
            for(int i=1;i<=p;i++)
            {
                scanf("%d%d%d%d",&x,&y,&x1,&y1);
                se[++cnt]=seg(x-1,y,y1,1,i);ly[++tot]=y;
                se[++cnt]=seg(x1,y,y1,-1,i);ly[++tot]=y1;
            }
            sort(a+1,a+1+m);
            sort(ly+1,ly+1+tot);
            sort(se+1,se+1+cnt);
            int ny=unique(ly+1,ly+1+tot)-ly-1,pos=1;
            build(1,ny,1);
            for(int i=1;i<=cnt;i++)
            {
                se[i].l=lower_bound(ly+1,ly+1+ny,se[i].l)-ly;
                se[i].r=lower_bound(ly+1,ly+1+ny,se[i].r)-ly;
            }
            for(int i=1;i<=m;i++)
            a[i].y=lower_bound(ly+1,ly+1+ny,a[i].y)-ly;
            int j=1,num=se[1].x;
            for(int i=1;i<=cnt;i++)
            {
                while(a[pos].x<=se[i].x&&pos<=m)pos++;
                for(;j<pos;j++)update(a[j].y,a[j].val,1,ny,1);
                j=pos;
                if(se[i].s==1)ans[se[i].id]=query(se[i].l,se[i].r,1,ny,1);
                else ans[se[i].id]=query(se[i].l,se[i].r,1,ny,1)-ans[se[i].id];
            }
            for(int i=1;i<=p;i++)
            printf("%lld
    ",ans[i]);
        }
        return 0;
    }
  • 相关阅读:
    关于跳槽你需要知道的
    Ping 命令的使用方法总结
    Linux 使用 su 切换用户提示 Authentication Failure 的解决方法
    《小强升职记——时间管理故事书》读书笔记
    记近期的几次面试经历
    每月书单_2014-06
    每月书单_2014-02
    交互式设计与用户体验
    读书笔记_探索式测试_混合探索式测试
    请慢慢移动……由于操作快慢导致的bug
  • 原文地址:https://www.cnblogs.com/chen99/p/11525013.html
Copyright © 2011-2022 走看看