p1968
我觉得这个评测机和我有仇,写了read+getchar都会超时这么多,最后好像是ios::sync_with_stdio(false);惹的祸...
昨天想找一些水题来写,就看到了这个模拟"水题",想了一下午都不知道怎么搞.
已知一些牛的颜色和位置,求连续相同颜色或连续两种颜色数量相同的区间右端点位置减左端点位置最长的距离.复杂度小于n^2.
(果然还是我太菜了,而且只会二分,对于这种题就很难搞.)
首先,这道题的答案不满足单调性,尺寸并不是在一个值之后就全部能取到的那种.所以不能写二分.
但是本题是一个模拟啊,不要想的那么恐怖.
先sort一下.
连续相同颜色只要从前向后扫一遍就好.
数量相同的话,对于每一个牛可以求出前缀和,维护一个数组记录前缀和i第一次出现的位置wei[i](在原结构体数组中的位置),如果当前前缀和数组上没有值,就把自己记录下来.否则可以用它来更新答案:ans=max(ans,o[i].x-o[wei[sum]+1].x);
这个过程中sum可能会变成负数,可以先把sum赋值成>=n的数,同时注意wei数组的大小.
wei[0]一定是0,为了区分0,更新过的和未更新过的,可以写一个循环使数组赋值为-1,然后写一句话:wei[sum]=0后再开始循环.
using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} return x*f; } int i,f; char b; int n,ans,sum; int wei[300001]; struct cow { int x,t; }o[100010]; inline bool Orz(cow a,cow b) { return a.x<b.x; } int main() { n=read(); for(i=1;i<=n;++i) { o[i].x=read(); b=getchar(); if(b=='G') o[i].t=1; else o[i].t=-1; } sort(o+1,o+1+n,Orz); for(i=1;i<=n;++i) { for(f=i+1;o[f].t==o[i].t&&f<=n;++f) {} f--; ans=(ans>o[f].x-o[i].x?ans:o[f].x-o[i].x); i=f; } for(i=0;i<=200000;++i) wei[i]=-1; sum=100000; wei[sum]=0; for(i=1;i<=n;++i) { sum+=o[i].t; if(wei[sum]==-1) wei[sum]=i; else ans=(ans>o[i].x-o[wei[sum]+1].x?ans:o[i].x-o[wei[sum]+1].x); } cout<<ans; }