Codechef SEAARC Sereja and Arcs (分块)
生活随笔
收集整理的這篇文章主要介紹了
Codechef SEAARC Sereja and Arcs (分块)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
我現在真的什么都不會了呢......
題目鏈接: https://www.codechef.com/problems/SEAARC
好吧,這題其實考察的是枚舉的功力……
題目要求的是\(ABAB\)的數量,這個不太好求,但是不同顏色區間對的總數和\(AABB,ABBA\)的都比較好求
補集轉化,求\(ans0,ans1,ans2\), 分別表示總數、\(AABB\)、\(ABBA\)的數量
\(ans0\)很好算
\(ans1\), 枚舉\(B\)的左端點
\(ans2\), 分塊討論
若\(A,B\)都是小顏色(該顏色塊的數量小于閾值),則枚舉\(A\)的左右端點,變成二維數點
若\(A\)是大顏色\(B\)是小顏色,則枚舉\(A\)的種類,然后枚舉\(B\)的種類和左右端點,推一下式子發現可以維護前綴和省去枚舉左端點
若\(B\)是大顏色,同理枚舉\(B\)的種類然后枚舉\(A\)的種類和左右端點,同樣省去枚舉左端點
從昨天下午做到今天上午。。
理論最優時間復雜度\(O(n\sqrt{n\log n})\)
代碼
#include<cstdio> #include<cstdlib> #include<cstring> #include<cassert> #include<vector> #include<cmath> #define llong long long using namespace std;const int N = 1e5; const int P = 1e9+7; const llong INV2 = 5e8+4; int nxt[N+3]; int lstpos[N+3]; int a[N+3]; int num[N+3]; int cnum[N+3]; llong tmp0[N+3],tmp1[N+3],tmp2[N+3]; vector<int> clrpos[N+3]; int n,m,B; llong ans1,ans2a,ans2b,ans2c,ans0,ans;llong C2(llong x) {return x*(x-1ll)/2ll%P;} llong update(llong &x,llong y) {x = (x+y)%P;}struct BITree {llong tr[N+3]; int siz;void addval(int lrb,llong val){while(lrb<=siz){update(tr[lrb],val);lrb += (lrb&(-lrb));}}llong querysum(llong rb){llong ret = 0ll;while(rb){update(ret,tr[rb]);rb -= (rb&(-rb));}return ret;}void clear(){for(int i=0; i<=siz; i++) tr[i] = 0ll;} } bit1,bit2;void getans0() //ans0=?ùóD??é?C(num,2)á?á?3??y??oí 2???AAAA {llong cur = 0ll;for(int i=1; i<=m; i++){llong tmp = C2(num[i]);update(ans0,cur*tmp%P);update(cur,tmp);} }void getans1() //2???AAAA {llong tmp = 0ll; //μ±?°×ü12í?é?????μ???êy for(int i=1; i<=n; i++){update(ans1,(tmp-C2(cnum[a[i]]))*(num[a[i]]-cnum[a[i]]-1)); //?a????é?×ü??êy???a???°μ???êy-1£?μèóú?a??oóμ???êy£?3?ò??°??μ?òìé???êy update(tmp,(llong)cnum[a[i]]); //?a????é????°μ???êy cnum[a[i]]++;} }void getans2a() //small-small 2???AAAA {bit1.siz = n; bit1.clear(); llong cur = 0ll;for(int i=1; i<=n; i++) //???ùóò??μ? {if(num[a[i]]<=B){int tnum = 0;for(int j=nxt[i]; j; j=nxt[j]){llong tmp = cur-bit1.querysum(j)-C2(tnum)+P+P; //>jμ?×ó??μ?μ???êy=×ü??êy??<=jμ???êy£?è¥μ?í?é?μ???êy(2???ioíj)update(ans2a,tmp);tnum++; //í?é???êy }for(int j=nxt[i]; j; j=nxt[j]) //óéóúê?óò??μ?D?óúj£??èDT??oó2é?ˉ {cur++; //???°????×ü??êy,?′bit1.querysum(i) bit1.addval(j,1);}}} }void getans2b() //large-small {for(int i=1; i<=m; i++) //???ùA??àà{if(num[i]>B) {tmp1[0] = 0ll; for(int j=1; j<=n; j++) tmp1[j] = tmp1[j-1]+(a[j]==i?1:0);for(int j=1; j<=m; j++) //???ùB??àà {if(num[j]<=B){llong cur = 0ll;for(int k=0; k<clrpos[j].size(); k++){int rb = clrpos[j][k];llong tmp = (num[i]-tmp1[rb])*cur%P;update(ans2b,tmp); update(cur,tmp1[rb]); //lb2??éμèóúrb, ?ùò??è?üD?ans2b?ù?üD?cur }}}}} }void getans2c() //large-large or small-large 2???AAAA {for(int i=1; i<=m; i++) //???ùBμ???àà {if(num[i]>B){tmp1[0] = 0; for(int j=1; j<=n; j++) tmp1[j] = tmp1[j-1]+(a[j]==i?1:0);for(int j=1; j<=m; j++) //???ùAμ???àà {if(i==j) continue;llong cur1 = 0ll,cur2 = 0ll;for(int k=0; k<clrpos[j].size(); k++) //???ùra{//?üD?ans2c int ra = clrpos[j][k];llong tmp = tmp1[ra]*tmp1[ra]%P*k%P;update(ans2c,tmp);tmp = tmp1[ra]*(-2ll*cur1-k)%P+P;update(ans2c,tmp);tmp = cur2+cur1+P;update(ans2c,tmp);//?üD?cur1,cur2 update(cur2,tmp1[ra]*tmp1[ra]);update(cur1,tmp1[ra]);}}}}ans2c = ans2c*INV2%P; }int main() {scanf("%d",&n); B = sqrt(n)/2;for(int i=1; i<=n; i++) scanf("%d",&a[i]),num[a[i]]++,m = max(m,a[i]),clrpos[a[i]].push_back(i);for(int i=1; i<=n; i++){nxt[i] = lstpos[a[i]];lstpos[a[i]] = i;}getans0();getans1();getans2a();getans2b();getans2c();ans = ((ans0-ans1-ans2a-ans2b-ans2c)%P+P)%P;printf("%lld\n",ans);return 0; } 與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Codechef SEAARC Sereja and Arcs (分块)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Codechef TRIPS Child
- 下一篇: Codechef SEAARC Sere