有 \(n\) 條魚,第 \(i\) 條魚的長度爲 \(L_i\),顏色是 \(C_i\)(\(C_i\) 只能是 'R','G','B')。
你須要從中挑出至少一條魚,要求挑出的魚中不能存在兩條魚 \(x,y\) 知足 \(2L_x\le L_y\)。
求能夠挑出 \(a\) 條紅魚、\(b\) 條綠魚、\(c\) 條藍魚的三元組 \((a,b,c)\) 的個數。
\(n\le 5\times 10^5\)node
將全部魚按 \(L\) 從小到大排序。
枚舉每條魚 \(l\) 爲 \(L\) 最小的魚,求在此基礎上能挑出的 \(L\) 最大的魚 \(r\)。設第 \([l,r]\) 條魚中有 \(a\) 條紅魚,\(b\) 條綠魚,\(c\) 條藍魚,則 \((0,0,0)\) 到 \((a,b,c)\) 這個立方體空間中的全部三維點都是能夠選的。問題轉化成了求 \(n\) 個立方體的體積並。
\(n\) 個立方體的前左下端點都是 \((0,0,0)\),這個性質很好,咱們能夠用掃描線倒序掃第一維,第2、三維組成的平面 必定是一個包含左下角的凸包。不難發現咱們要支持快速將一個前綴對一個參數取 max,以及總體求和,直接線段樹就完了。時間 \(O(n\log n)\)。c++
固然也能夠維護一個 set 記錄第2、三維組成的平面上的凸包的每一個頂點,區間更新 max 時暴力刪掉中間全部被覆蓋掉的頂點便可。spa
#include<bits/stdc++.h> using namespace std; typedef long long ll; inline int rd(){ char c=getchar();int x=0,flag=1; for(;c<'0'||c>'9';c=getchar())if(c=='-')flag=-1; for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0'; return x*flag; } struct fish{ int l,c; friend inline bool operator < (fish a,fish b){ return a.l>b.l; } }a[500010]; struct node{ int x,y,z; friend inline bool operator < (node a,node b){ return a.x>b.x; } }p[500010]; struct seg_tree{ ll sum;int tag,mx,mn; }st[2000010]={0}; int n,sz[3]={0}; inline void pushdown(int s,int l,int r){ if(!st[s].tag) return; int mid=(l+r)>>1,v=st[s].tag; st[s<<1].tag=st[s<<1].mx=st[s<<1].mn=v; st[s<<1].sum=(ll)v*(mid-l+1); st[s<<1|1].tag=st[s<<1|1].mx=st[s<<1|1].mn=v; st[s<<1|1].sum=(ll)v*(r-mid); return (void)(st[s].tag=0); } inline void pushup(int s){ st[s].sum=st[s<<1].sum+st[s<<1|1].sum; st[s].mx=max(st[s<<1].mx,st[s<<1|1].mx); st[s].mn=min(st[s<<1].mn,st[s<<1|1].mn); return; } inline void upd(int s,int l,int r,int x,int y,int v){ if(st[s].mn>=v) return; if(x<=l&&r<=y&&st[s].mx<=v){ st[s].tag=st[s].mx=st[s].mn=v; st[s].sum=(ll)v*(r-l+1); return; } int mid=(l+r)>>1;pushdown(s,l,r); if(x<=mid) upd(s<<1,l,mid,x,y,v); if(mid<y) upd(s<<1|1,mid+1,r,x,y,v); return pushup(s); } int main(){ n=rd(); for(int i=1;i<=n;i++){ int l=rd();char c[2];scanf("%s",c); a[i]=(fish){l,(c[0]=='R')?0:(c[0]=='G')?1:2}; } sort(a+1,a+n+1); for(int i=1,j=1;i<=n;i++){ for(;j<=n&&(a[j].l<<1)>a[i].l;j++) sz[a[j].c]++; p[i]=(node){sz[0]+1,sz[1]+1,sz[2]+1}; sz[a[i].c]--; } sort(p+1,p+n+1); ll ans=0; for(int i=n+1,j=1;i;i--){ for(;j<=n&&p[j].x==i;j++) upd(1,1,n+1,1,p[j].y,p[j].z); ans+=st[1].sum; } return printf("%lld\n",ans-1),0; }