P3105 [USACO14OPEN]公平的摄影Fair Photography
Posted renjianshige
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3105 [USACO14OPEN]公平的摄影Fair Photography相关的知识,希望对你有一定的参考价值。
题意翻译
在数轴上有 NNN 头牛,第 iii 头牛位于 xi(0≤xi≤109)x_i:(0le x_ile 10^9)xi?(0≤xi?≤109) 。没有两头牛位于同一位置。
有两种牛:白牛和花斑牛。保证至少有一头白牛。你可以把白牛涂成花斑牛,不限数量,不限哪只。
找一段尽量长的区间,使得区间的两端点均有一头牛,且区间中白牛与花斑牛的数量相等。试求区间长度。
感谢 @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.
输入输出样例
说明
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; }
以上是关于P3105 [USACO14OPEN]公平的摄影Fair Photography的主要内容,如果未能解决你的问题,请参考以下文章
2021.8.14提高B组模拟6T4 + P7555 [USACO21OPEN] Maze Tac Toe (dfs)
2021.8.14提高B组模拟6T3 + P7527 [USACO21OPEN] United Cows of Farmer John (树状数组)
2021.8.14提高B组模拟6T3 + P7527 [USACO21OPEN] United Cows of Farmer John (树状数组)