Loj#3511【USACO 2021 Open, P】T1 United Cows of Farmer John
阿新 • • 發佈:2021-08-19
【USACO 2021 Open, P】T1 United Cows of Farmer John
題目大意
\(N\) 頭奶牛,每條隊伍的隊頭和隊尾都與隊伍中其他牛的種類不同,還需選出隊伍中的一個作為領隊,也需與其他牛種類不同。
求方案數。 \(N \le 2e5\)
解法
將三個領隊分別稱作領頭、領隊和領尾。
先不考慮領隊。
線段樹維護兩個值:區間內的 領頭數量 和 領頭和領尾匹配對數(領尾範圍無限制)。
具體是對於每次加入一個點,將對應 \(b_i\) 的上一個領頭刪掉,並使所有 \(g_{l,r}+=f_{l,r}\) ,將當前點記作新的領頭。
然後考慮對於一個領隊位置為 \(K\)
code
#include<bits/stdc++.h> #define fo(i,a,b) for(int i=a;i<=b;++i) #define fd(i,a,b) for(int i=a;i>=b;--i) #define ll long long #define ls (t<<1) #define rs (t<<1|1) using namespace std; const ll N=2e5+10; ll n,a[N],ans,f[N<<2],g[N<<2],tag[N<<2]; ll t[N],l[N],r[N],cnt,Ans[N]; struct node{ ll t,v,l,r,id; }b[N*2]; bool cmp(node a,node b){return a.t<b.t;} void push(ll t){ g[ls]+=f[ls]*tag[t]; g[rs]+=f[rs]*tag[t]; tag[ls]+=tag[t];tag[rs]+=tag[t]; tag[t]=0; } void add(ll t,ll l,ll r,ll L,ll R){ if(L<=l && r<=R){ g[t]+=f[t]; ++tag[t]; return; } ll mid=l+r>>1; if(L<=mid)add(ls,l,mid,L,R); if(R>mid)add(rs,mid+1,r,L,R); g[t]=g[ls]+g[rs]; } void modify(ll t,ll l,ll r,ll x,ll y){ f[t]+=y; if(l==r)return; if(tag[t])push(t); ll mid=l+r>>1; if(x>mid)modify(rs,mid+1,r,x,y); else modify(ls,l,mid,x,y); } ll query(ll t,ll l,ll r,ll L,ll R){ if(L<=l && r<=R)return g[t]; if(tag[t])push(t); ll mid=l+r>>1,ret=0; if(L<=mid)ret+=query(ls,l,mid,L,R); if(R>mid)ret+=query(rs,mid+1,r,L,R); return ret; } int main(){ scanf("%lld",&n); fo(i,1,n){ scanf("%lld",&a[i]); l[i]=t[a[i]]; t[a[i]]=i; } fo(i,1,n)t[i]=n+1; fd(i,n,1){ r[i]=t[a[i]]; t[a[i]]=i; } fo(i,2,n-1){ ll L=l[i]+1,R=r[i]-1; if(L<i && i<R){ b[++cnt]=(node){i,-1,L,i-1,i}; b[++cnt]=(node){R,1,L,i-1,i}; } } sort(b+1,b+cnt+1,cmp); for(ll i=1,it=1;i<=cnt && it<=cnt;++i){ if(l[i])modify(1,1,n,l[i],-1); if(l[i]+1<i)add(1,1,n,l[i]+1,i-1); modify(1,1,n,i,1); for(;it<=cnt && b[it].t==i;++it){ ans+=b[it].v*query(1,1,n,b[it].l,b[it].r); Ans[b[it].id]+=b[it].v*query(1,1,n,b[it].l,b[it].r); } } printf("%lld\n",ans); // fo(i,1,n)printf("%lld ",Ans[i]); // printf("\n"); return 0; }