zoukankan      html  css  js  c++  java
  • P3105 [USACO14OPEN]公平的摄影Fair Photography

    题意翻译

    在数轴上有 NNN 头牛,第 iii 头牛位于 xi(0≤xi≤109)x_i:(0le x_ile 10^9)xi(0xi109) 。没有两头牛位于同一位置。
    有两种牛:白牛和花斑牛。保证至少有一头白牛。你可以把白牛涂成花斑牛,不限数量,不限哪只。
    找一段尽量长的区间,使得区间的两端点均有一头牛,且区间中白牛与花斑牛的数量相等。试求区间长度。

    感谢 @Planet6174 的翻译

    题目描述

    FJ's N cows (2 <= N <= 100,000) are standing at various positions along a long one-dimensional fence. The ith cow is standing at position x_i (an integer in the range 0...1,000,000,000) and is either a plain white cow or a spotted cow. No two cows occupy the same position, and there is at least one white cow.

    FJ wants to take a photo of a contiguous interval of cows for the county fair, but in fairness to his different cows, he wants to ensure there are equal numbers of white and spotted cows in the photo. FJ wants to determine the maximum size of such a fair photo, where the size of a photo is the difference between the maximum and minimum positions of the cows in the photo.

    To give himself an even better chance of taking a larger photo, FJ has with him a bucket of paint that he can use to paint spots on an arbitrary subset of his white cows of his choosing, effectively turning them into spotted cows. Please determine the largest size of a fair photo FJ can take, given that FJ has the option of painting some of his white cows (of course, he does not need to paint any of the white cows if he decides this is better).

    输入输出格式

    输入格式:

    * Line 1: The integer N.

    * Lines 2..1+N: Line i+1 contains x_i and either W (for a white cow) or S (for a spotted cow).

    输出格式:

    * Line 1: The maximum size of a fair photo FJ can take, after possibly painting some of his white cows to make them spotted.

    输入输出样例

    输入样例#1: 复制
    5 
    8 W 
    11 S 
    3 W 
    10 W 
    5 S 
    
    输出样例#1: 复制
    7 
    

    说明

    There are 5 cows. One of them is a white cow at position 8, and so on.

    FJ takes a photo of the cows from positions 3 to positions 10. There are 4 cows in this range -- 3 white and 1 spotted -- so he needs to paint one of the white cows to make it spotted.

    题解:

      发现这个题目本质上是找一个区间,使得(白牛的数量-花牛的数量)%2==0,所以想到前缀和,记sum1为白牛的前缀和,sum2为花牛的前缀和。区间i,j合法只有区间设k=(sum1[i]-sum1[j-1])-(sum2[j-1]-sum2[j-1])。必须k>=0且k%2==0,给式子变一下形,就是k=sum1[i]-sum2[i]-(sum2[j-1]-sum1[j-1])。分类讨论sum1[i]-sum2[i]的奇偶性质,把sum2[j-1]-sum1[j-1]丢到两棵线段树里,维护sum2[j-1]-sum1[j-1]的最大值就可以判断区间何不合法,因为要枚举右端点,时间复杂度nlogn.

    代码:

      

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #include <iostream>
    #define MAXN 104000
    #define ll long long
    #define RG register
    using namespace std;
    
    struct tree{
        int l,r,maxx;
    }a[3][MAXN*4];
    
    struct cow{
        int pl,co;
        void read(){
            char x;
            scanf("%d%c%c",&pl,&x,&x);
            if(x=='W') co=1;
            else co=0;
        }
    }b[MAXN];
    
    int sum1[MAXN],sum2[MAXN];
    int n;
    
    inline bool cmp(cow x,cow y){
        if(x.pl<y.pl) return 1;
        return 0;
    }
    
    int check(int x){
        if(abs(x)%2==0) return 2;
        else return 1;
    }
    
    int query(int xv,int l,int r,int id,int x){
        int L=a[id][xv].l,R=a[id][xv].r,mid=(L+R)/2;
        if(L==R) return L;
        if(a[id][xv*2].maxx+x>=0) return query(xv*2,l,mid,id,x);
        else if(a[id][xv*2+1].maxx+x>=0) return query(xv*2+1,mid+1,r,id,x);
        else return 0;
    }
    
    void insert(int xv,int ps,int zhi,int id){
        int l=a[id][xv].l,r=a[id][xv].r,mid=(l+r)/2;
        if(l==r){
            a[id][xv].maxx=zhi;
            return;
        }
        if(ps<=mid) insert(xv*2,ps,zhi,id);
        else insert(xv*2+1,ps,zhi,id);
        a[id][xv].maxx=max(a[id][xv*2].maxx,a[id][xv*2+1].maxx);
    }
    
    void work(){
        int ans=0;
        for(int i=1;i<=n;i++){
            int hh=sum1[i]-sum2[i],l=0;int id=check(hh);
            if((sum1[i]-sum2[i]+sum2[0]-sum1[0])%2==0&&sum1[i]-sum2[i]+sum2[0]-sum1[0]>=0)
                ans=max(ans,b[i].pl-b[1].pl);
            if(hh+a[id][1].maxx>=0)
                l=query(1,1,i,id,hh);
            if(l)
                ans=max(ans,b[i].pl-b[l+1].pl);
            hh=sum2[i]-sum1[i];id=check(hh);
            insert(1,i,sum2[i]-sum1[i],id);
        }
        printf("%d",ans);
    }
    
    void build(int id,int l,int r){
        if(l==r){
            a[1][id].l=a[2][id].l=l,a[1][id].r=a[2][id].r=r;
            a[1][id].maxx=a[2][id].maxx=-(1<<30);
            return;
        }
        a[1][id].maxx=a[2][id].maxx=-(1<<30);
        a[1][id].l=a[2][id].l=l,a[1][id].r=a[2][id].r=r;
        int mid=(l+r)/2;
        build(id*2,l,mid),build(id*2+1,mid+1,r);
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) b[i].read();
        sort(b+1,b+n+1,cmp);
        for(int i=1;i<=n;i++) if(b[i].co==1) sum1[i]=sum1[i-1]+1,sum2[i]=sum2[i-1]; else sum2[i]=sum2[i-1]+1,sum1[i]=sum1[i-1];
        build(1,1,n);
        work();
        return 0;
    }
  • 相关阅读:
    世界视频编码器大赛结果揭晓,腾讯V265编码器勇夺两项第一
    IDEA实用教程(六)—— 全局设置的两种方式
    IDEA实用教程(五)——配置IDEA的JVM内存值
    IDEA实用教程(四)—— 创建JavaSE工程
    IDEA实用教程(三)
    IDEA实用教程(二)
    emlog博客的安装教程
    IDEA实用教程(一)
    阿里云轻量应用服务器快照的使用及注意事项
    mysql5.5安装教程
  • 原文地址:https://www.cnblogs.com/renjianshige/p/9457492.html
Copyright © 2011-2022 走看看