zoukankan      html  css  js  c++  java
  • 【九校3D2T3】世界第一的猛汉王

    【问题描述】

    卡普地公司举办了「世界第一的猛汉王」全球大会,来自世界各地的猛汉为了争夺「猛汉王」的名号前来一决高下。现在举行的是弓箭组选拔赛。卡普地公司为比赛新建了一张PVP地图——「猛汉竞技场」。有许多使用弓的猛汉在这里互相较量。他们中的一些装填了「接击瓶」,这使得他们在接近战中会占有一定优势,但是在远程战中会相当劣势。具体来说如下:

    假设q装填了「接击瓶」而p没有,则当他们的曼哈顿距离大于D时,p压制q,反之q压制p。如果pq都装填了「接击瓶」或者都没有,则他们之间仍然会存在一个客观上的单向压制关系,但是在比赛刚开始时无法得知。

    竞技场上一共有n+m个猛汉,其中n个装填了「接击瓶」,另外m个没有。每个猛汉降临到竞技场时有一个坐标(x, y)。Mark Douglas作为上一届的猛汉王正在观看这场比赛,他希望得知场上有多少个「猛汉三角」。「猛汉三角」是指三个人uvw满足u压制vv压制ww压制u,且三人中至少有一人装填了「接击瓶」且至少有一人没有。由于场上尚存在一些不明了的压制关系,所以Mark希望知道可能的「猛汉三角」数量的最小值和最大值。

    【输入格式】

    输入文件名为mhw.in

    输入第一行为三个正整数n m D

    接下来n行每行两个正整数x y,表示装填了「接击瓶」的猛汉的坐标。

    接下来m行每行两个正整数x y,表示没有装填「接击瓶」的猛汉的坐标。

    可能有多个猛汉站在同一个位置。

    【输出格式】

    输出文件名为mhw.out

     输出两个数min max,表示答案的最小值和最大值。

    【样例输入与输出】

    example_mhw1.in

    example_mhw1.out

    2 2 1

    1 2

    1 1

    3 1

    2 2

    0 2

     

    难度确实大!

    首先我们将猛汉们分为两个阵营(记为黑色与白色)。我们一个猛汉三角就是形如a->c->b(a,b同阵营),然后在确定a,b之间的压制关系得到最小或者最大值。

    我们以白色阵营为例。我们设cover[v]为v压制的对方阵营的数量,cover[v,u]为v,u共同压制的对方阵营的数量。minans=sum minleft { cover[v]-cover[v,u] 
ight cover[u]-cover[v,u]},maxans同理。

    minans=sum minleft { cover[v] 
ight cover[u]}-sum cover[v,u]。对于cover[v,u],我们就算另一方阵营对sum cover[v,u]的贡献就行了。如果一个猛汉被对面的k个人压制,那么他对sum cover[v,u]的贡献就是frac{k*(k-1)}{2}

    求cover数组可以用扫描+线段树。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<ctime>
    #include<queue>
    #define ll long long
    #define N 100005
    
    using namespace std;
    inline ll Get() {ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}
    
    ll n,m,lim;
    ll mn,mx;
    ll cc;
    ll d[N*6];
    ll cnt;
    ll c[2][N];
    
    struct line {
        ll x,op,col,id;
        ll l,r;
        bool operator <(const line &a)const {
            if(x!=a.x) return x<a.x;
            return op<a.op;
        }
    }st[N*6];
    
    struct tree {
        ll l,r;
        ll sum[2];
    }tr[N*25];
    
    void build(ll v,ll l,ll r) {
        tr[v].l=l,tr[v].r=r;
        if(l==r) return ;
        ll mid=l+r>>1;
        build(v<<1,l,mid),build(v<<1|1,mid+1,r);
    }
    
    void Modify(ll v,ll l,ll r,ll tag,ll f) {
        if(tr[v].l>r||tr[v].r<l) return ;
        if(l<=tr[v].l&&tr[v].r<=r) {
            tr[v].sum[tag]+=f;
            return ;
        }
        Modify(v<<1,l,r,tag,f),Modify(v<<1|1,l,r,tag,f);
    }
    
    ll query(ll v,ll pos,ll tag) {
        if(tr[v].l>pos||tr[v].r<pos) return 0;
        if(tr[v].l==tr[v].r) return tr[v].sum[tag];
        return query(v<<1,pos,tag)+query(v<<1|1,pos,tag)+tr[v].sum[tag];
    }
    
    void work() {
        for(ll i=1;i<=cnt;i++) {
            if(st[i].op==-1) {
                Modify(1,st[i].l,st[i].r,st[i].col,1);
            } else if(st[i].op==0) {
                c[st[i].col][st[i].id]=query(1,st[i].l,st[i].col^1);
            } else {
                Modify(1,st[i].l,st[i].r,st[i].col,-1);
            }
        }
    }
    
    int main() {
        n=Get(),m=Get(),lim=Get();
        ll a,b,x,y;
        for(ll i=1;i<=n;i++) {
            a=Get(),b=Get();
            x=a+b,y=a-b;
            st[++cnt]=(line) {x-lim,-1,0,i,y-lim,y+lim};
            st[++cnt]=(line) {x,0,0,i,y};
            st[++cnt]=(line) {x+lim,1,0,i,y-lim,y+lim};
            d[++d[0]]=y;
            d[++d[0]]=y+lim;
            d[++d[0]]=y-lim;
        }
        for(ll i=1;i<=m;i++) {
            a=Get(),b=Get();
            x=a+b,y=a-b;
            st[++cnt]=(line) {x-lim,-1,1,i,y-lim,y+lim};
            st[++cnt]=(line) {x,0,1,i,y};
            st[++cnt]=(line) {x+lim,1,1,i,y-lim,y+lim};
            d[++d[0]]=y;
            d[++d[0]]=y+lim;
            d[++d[0]]=y-lim;
        }
        sort(st+1,st+1+cnt);
        sort(d+1,d+1+d[0]);
        cc=unique(d+1,d+1+d[0])-d;
        for(ll i=1;i<=cnt;i++) {
            st[i].l=lower_bound(d+1,d+cc,st[i].l)-d;
            st[i].r=lower_bound(d+1,d+cc,st[i].r)-d;
        }
        build(1,1,cc);
        
        work();
        for(ll i=1;i<=m;i++) c[1][i]=n-c[1][i];
        sort(c[0]+1,c[0]+1+n);
        sort(c[1]+1,c[1]+1+m);
        
        for(ll i=1;i<=n;i++) {
            mn+=(n-i)*c[0][i];
            mx+=(i-1)*c[0][i];
            ll x=1ll*(m-c[0][i])*(m-c[0][i]-1)/2;
            mn-=x,mx-=x;
        }
        for(ll i=1;i<=m;i++) {
            mn+=1ll*(m-i)*c[1][i];
            mx+=1ll*(i-1)*c[1][i];
            ll x=1ll*(n-c[1][i])*(n-c[1][i]-1)/2;
            mn-=x,mx-=x;
        }
        cout<<mn<<" "<<mx;
        return 0;
    }
  • 相关阅读:
    python——socket,IO多路复用(select),socket server实现多并发
    python——多线程,多进程,协程
    python——装饰器,迭代器,生成器
    time模块,datetime模块
    re模块,paramiko模块
    Freemaker中使用中括号来包含标签
    Freemaker中使用中括号来包含标签
    freemarker Velocity获取request,session
    freemarker Velocity获取request,session
    freemarker Velocity获取request,session
  • 原文地址:https://www.cnblogs.com/hchhch233/p/9996736.html
Copyright © 2011-2022 走看看