【树状数组】CF961E Tufurama
挺巧妙的數據結構題(不過據說這是一種套路?
E. Tufurama
One day Polycarp decided to rewatch his absolute favourite episode of well-known TV series "Tufurama". He was pretty surprised when he got results only for season 7 episode 3 with his search query of "Watch Tufurama season 3 episode 7 online full hd free". This got Polycarp confused — what if he decides to rewatch the entire series someday and won't be able to find the right episodes to watch? Polycarp now wants to count the number of times he will be forced to search for an episode using some different method.TV series have?n?seasons (numbered?1?through?n), the?i-th season has?ai?episodes (numbered?1?through?ai). Polycarp thinks that if for some pair of integers?x?and?y?(x?<?y) exist both season?x?episode?y?and season?y?episode?x?then one of these search queries will include the wrong results. Help Polycarp to calculate the number of such pairs!
InputThe first line contains one integer?n?(1??≤?n??≤??2·10^5)?— the number of seasons.
The second line contains?n?integers separated by space?a1,?a2,?...,?an?(1?≤?ai?≤?10^9)?— number of episodes in each season.
OutputPrint one integer — the number of pairs?x?and?y?(x?<?y) such that there exist both season?x?episode?y?and season?y?episode?x.
題目大意
有一部電視劇有n季,每一季有ai集。定義二元組(i,j):存在第i季有第j集。求(i,j)與(j,i)同時合法(i<j)的對數。
真實題意就是:求<i,j>對數,使得a[i]≥j,a[j]≥i并且(i<j)
?看上去很可做的樣子,對吧……
題目分析
基礎的暴力
從1..n季,每一季都分別判斷對答案的貢獻。
例如對于?4 \n?3 5 1 2?,依次檢查(1,2)是否存在(2,1);(1,3)是否存在(3,1)……
首先發現a[i]對于答案的貢獻最大也就是到n為止,那么讀入時候先取個min(n)。
考慮一下check()是O(n)的,所以總復雜度是O(n2)的。
BIT做法
像很多其他題一樣,對于這樣的、關于元素大小關系之間的限制的題目,先排個序總是能夠解決個一維限制掉去的。
我們使用一個結構體node x,x.i表示季數;x.a表示該季的集數。首先對x.a排序。那么就變成這個樣子:
p[].a(j) 3 5 1 2p[].i(i) 1 2 3 4
|
|
p[].a(j) 1 2 3 4 (取min之后)
p[].i(i) 3 4 1 2
先考慮每次的統計,那么只要ans+=query(a[i])就可以了。意思就是說ans加上1..a[i]季的貢獻(其中每一季的貢獻要么是0要么是1,但是由于之后會有修改,所以我們用BIT維護)
接著考慮修改,設立一個now指向當前最小合法的p[]。這個now用來更新那些已經?過氣?沒有貢獻的答案。
這里「沒有貢獻的答案」指的是p[now].a<i的情況。說人話就是p[now]的電視劇集數太小了,已經不會再有貢獻了,因此now++,判斷下一個p[]是否可能會對答案有貢獻。個人感覺有那么一點相似 單調隊列 和 wqs二分 的情況(但是我不是非常清楚)?
為了去除這些沒有貢獻的季數的影響,我們只需將p[now].i位置在樹狀數組上-1即可。意思是說這個季數在之后的統計上都不會有貢獻了。
?
1 #include<bits/stdc++.h> 2 using namespace std; 3 long long ans; 4 int n,now,a[200035]; 5 struct node 6 { 7 int a,i; 8 bool operator < (node &xx) const 9 { 10 return a < xx.a; 11 } 12 }p[200035]; 13 int f[200035]; 14 int read() 15 { 16 char ch = getchar();int num = 0; 17 for (; !isdigit(ch); ch = getchar()); 18 for (; isdigit(ch); ch = getchar()) 19 num = (num<<3)+(num<<1)+ch-48; 20 return num; 21 } 22 int lowbit(int x){return x&-x;} 23 void add(int x, int c){for (; x<=n+1; x+=lowbit(x))f[x]+=c;} 24 int query(int x) 25 { 26 int ret = 0; 27 for (; x; x-=lowbit(x)) 28 ret += f[x]; 29 return ret; 30 } 31 int main() 32 { 33 n = read();now = 1; 34 for (int i=1; i<=n; i++) 35 a[i] = min(read(), n+1), p[i].a = a[i], p[i].i = i, add(i, 1); 36 sort(p+1, p+n+1); 37 for (int i=1; i<=n; i++) 38 { 39 while (now<=n && p[now].a < i)add(p[now++].i, -1); 40 ans += query(a[i]); 41 if (a[i] >= i)ans--; 42 } 43 cout << ans / 2 << endl; 44 return 0; 45 }?
另附其他做法
其他人用BIT維護也挺巧妙的(但是我覺得初看時候有點云里霧里啊)
1.Educational Codeforces Round 41 E. Tufurama (961E) BIT做法
2.Codeforces 961E - Tufurama 【樹狀數組】 BIT做法
3.Codeforces - 961E Tufurama set+BIT
4.CF 961E Tufurama 跟我一樣的
?
?
END
?
轉載于:https://www.cnblogs.com/antiquality/p/8746718.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的【树状数组】CF961E Tufurama的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c# 窗体启动后自动执行 Form_Lo
- 下一篇: spring data jpa upd