题解:P6859 蝴蝶与花

· · 题解

树状树组 + set 短代码。1.4K写完才知道也不算很短

容易考虑奇偶性。 :::info[分析]

都比较显然。 ::: 上述过程大概就是对最大合法的 s 收缩,而且尽量在 r 收缩。

特判 \sum\limits_{i=1}^na_i<s

考虑先树状树组二分最小的 r'' 使得 \sum\limits_{i=1}^{r''}a_i\ge s

若不等号取等则 l=1,下文不考虑。

否则,用 set 维护 \{i|a_i=1\},对 r'' lowerbound() 一下使得 a_{r'-1}=1

一般情况下:

($1$)若 $l=1+$`*begin()` 容易求 $r$。 ($2$)否则 $r=r'$,$l\le$`*begin()` 时容易求 $l$,否则不如($1$)。 特别地,若不存在 $r'$,显然 $l=1+$`*begin()`,然后判断是否合法。 :::success[code] ```cpp #include<bits/stdc++.h> using namespace std; typedef long long ll; const ll N=2e6+10; ll a[N],n,m,x,y,w,c,d; set<ll> s; void rd(ll &x){ while((d=getchar())<48); do{x=d-48+x*10;}while((d=getchar())>47); } int main(){ rd(n),rd(m); for(ll i=1;i<=n;i++){ x=0,rd(x),w+=x; for(ll j=n-i+1;j<=n;j+=j&-j) a[j]+=x; if(x&1) s.insert(i);//x } while(m--){ c=x=y=0,rd(c),rd(x); if(c=='C'-'0'){ rd(y); if(y==1&&!s.count(x))//y s.insert(x),y=-1; else if(y==2&&s.count(x)) s.erase(x),y=1; else y=0; w+=y; for(ll j=n-x+1;j<=n;j+=j&-j) a[j]+=y; }else{ y=0,x=w-x; ll t=0; if(x==w||x<0){printf("none\n"); continue;} for(ll j=1<<20;j;j>>=1) if(y+j<=n&&t+a[y+j]<=x) y+=j,t+=a[y]; y=n-y+1; if(t==x) {printf("1 %lld\n",y-1); continue;} auto p=s.upper_bound(y-1); if(p==s.end()){ p=s.begin(); if(p==s.end()||(*p-1)*2>x) printf("none\n"); else printf("%lld %lld\n",*p+1,n-x/2+*p-1); continue; } t-=(*p-y)*2+1,y=*p; ll f=x-t>>1,g=*s.begin(); if(f<g) printf("%lld %lld\n",f+1,y); else printf("%lld %lld\n",g+1,y-1-(x-t)/2+g); } } return 0; } ``` ::: 后记:注意输入量!**尤其是 `char` 的输入!** 本题输入 $3\times10^6$ 个 `long long` 和 $10^6$ 个 `char`。 很多人 `cin` `char`,如果习惯 `scanf` 不会关同步流本题极易导致 `TLE`。 而且 `scanf` 占用时间也不少。