BZOJ_2743_[HEOI2012]采花_離線+樹狀數組
阿新 • • 發佈:2018-04-20
-i highlight 離我 她有 bzoj 編程 連續 以及 pos
第一行四個空格隔開的整數n、c以及m。
接下來一行n個空格隔開的整數,每個數在[1, c]間,第i個數表示第i朵花的顏色。
接下來m行每行兩個空格隔開的整數l和r(l ≤ r),表示女仆安排的行程為公主經過第l到第r朵花進行采花。
1 2 2 3 1
1 5
1 2
2 2
2 3
3 5
0
0
1
0
【樣例說明】
詢問[1, 5]:公主采顏色為1和2的花,由於顏色3的花只有一朵,公主不采;詢問[1, 2]:顏色1和顏色2的花均只有一朵,公主不采;
詢問[2, 2]:顏色2的花只有一朵,公主不采;
詢問[2, 3]:由於顏色2的花有兩朵,公主采顏色2的花;
詢問[3, 5]:顏色1、2、3的花各一朵,公主不采。
BZOJ_2743_[HEOI2012]采花_離線+樹狀數組
Description
蕭蕓斕是Z國的公主,平時的一大愛好是采花。今天天氣晴朗,陽光明媚,公主清晨便去了皇宮中新建的花園采花 。花園足夠大,容納了n朵花,花有c種顏色(用整數1-c表示),且花是排成一排的,以便於公主采花。公主每次 采花後會統計采到的花的顏色數,顏色數越多她會越高興!同時,她有一癖好,她不允許最後自己采到的花中,某 一顏色的花只有一朵。為此,公主每采一朵花,要麽此前已采到此顏色的花,要麽有相當正確的直覺告訴她,她必 能再次采到此顏色的花。由於時間關系,公主只能走過花園連續的一段進行采花,便讓女仆福涵潔安排行程。福涵 潔綜合各種因素擬定了m個行程,然後一一向你詢問公主能采到多少朵花(她知道你是編程高手,定能快速給出答 案!),最後會選擇令公主最高興的行程(為了拿到更多獎金!)。Input
Output
共m行,每行一個整數,第i個數表示公主在女仆的第i個行程中能采到的花的顏色數。Sample Input
5 3 51 2 2 3 1
1 5
1 2
2 2
2 3
3 5
Sample Output
20
0
1
0
【樣例說明】
詢問[1, 5]:公主采顏色為1和2的花,由於顏色3的花只有一朵,公主不采;詢問[1, 2]:顏色1和顏色2的花均只有一朵,公主不采;
詢問[2, 3]:由於顏色2的花有兩朵,公主采顏色2的花;
詢問[3, 5]:顏色1、2、3的花各一朵,公主不采。
HINT
【數據範圍】
對於100%的數據,1 ≤ n ≤ 10^6,c ≤ n,m ≤10^6。
分析:
看起來莫隊可做,但數據範圍就是為了卡這個的,於是我們考慮同樣是離線的另一種做法。
首先對於每個花,求出下一次出現顏色相同的花的位置$nxt[]$ ,如果沒有則$nxt[]$ 為0。
然後把詢問搞下來,按詢問的左端點升序排序。
一開始,我只計算每個花第一次出現時的貢獻。
掃一遍數組,假設我當前在$i$ 這個位置,離我最近的詢問左端點是$j$ ,那我們要舍棄掉$i$ 到$j-1$ 這部分的貢獻。
刪除第$i$ 個數,對右端點在$i+1\thicksim nxt[i]-1$ 的這些需要$-1$ ,對右端點在$nxt[i]\thicksim nxt[nxt[i]]-1$ 的這部分$+1$ ,然後樹狀數組維護一下整個操作即可。
代碼:
#include <stdio.h> #include <string.h> #include <algorithm> #include <stdlib.h> using namespace std; #define N 1000050 int n,v[N],c,m,b[N],nxt[N],now[N],ans[N]; struct A { int l,r,pos; }a[N]; bool cmp(const A &x,const A &y) { if(x.l==y.l) return x.r<y.r; return x.l<y.l; } void fix(int x,int v) { for(;x<=n;x+=x&(-x)) b[x]+=v; } int inq(int x) { int re=0; for(;x;x-=x&(-x)) re+=b[x]; return re; } int main() { scanf("%d%d%d",&n,&c,&m); int i; for(i=1;i<=n;i++) scanf("%d",&v[i]); for(i=1;i<=m;i++) { scanf("%d%d",&a[i].l,&a[i].r); a[i].pos=i; } sort(a+1,a+m+1,cmp); for(i=n;i;i--) { nxt[i]=now[v[i]]; now[v[i]]=i; } for(i=1;i<=n;i++) { if(nxt[i]) fix(nxt[i],1); if(nxt[nxt[i]]) fix(nxt[nxt[i]],-1); } int fafa=1; for(i=1;i<=m;i++) { while(fafa<a[i].l) { if(nxt[fafa]) fix(nxt[fafa],-1); if(nxt[nxt[fafa]]) fix(nxt[nxt[fafa]],1); fafa++; } ans[a[i].pos]=inq(a[i].r)-inq(a[i].l-1); } for(i=1;i<=m;i++) printf("%d\n",ans[i]); }
BZOJ_2743_[HEOI2012]采花_離線+樹狀數組