BZOJ4826: [Hnoi2017]影魔
阿新 • • 發佈:2017-09-10
mem 上下 cnblogs http 最大值 clu memory www 自己的
Submit: 550 Solved: 300
[Submit][Status][Discuss]
第一行 n,m,p1,p2
第二行 n 個數:k[1],k[2],...,k[n]
接下來 m 行,每行兩個數 a,b,表示詢問區間[a,b]中的靈魂對會為影魔提供多少攻擊力。
1 <= n,m <= 200000;1 <= p1,p2 <= 1000
7 9 5 1 3 10 6 8 2 4
1 7
1 9
1 3
5 9
1 5
39
4
13
16
思路{
和去年的序列有點像啊...
對於一個點,單獨計算其作為區間最大值的貢獻,所以單調棧求出 $ L[i] $ 為左邊第一個大於它的數的位置, $ R[i] $ 為右邊第一個小於等於它的數的位置。
$ P1 $的貢獻只有點對 $ (L[i],R[i]) $ ,$P2$的貢獻又有 $ (L[i],j) $ , $ j $ 所屬的範圍是 $ (i,R[i]) $ ,和 $ (j,R[i]) $ , $ j $ 所屬的範圍是 $ (L[i],i) $.
那麽在平面內抽象成一條條線段,詢問抽象成兩條平行於 $x$ 軸的線段,
由於單獨考慮點,每條直線y值表示所代表的點.
每條線段左右端點即為所產生的貢獻範圍.那線段的左右端點和上下端點都是$L,R$了.
那麽就是求詢問所代表的區間內的權值和了!!
用掃描線+區間修改樹狀數組維護這個東西即可.
這麽說來應該也可以用掃描線來解決去年的序列了.
}
4826: [Hnoi2017]影魔
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 550 Solved: 300
[Submit][Status][Discuss]
Description
影魔,奈文摩爾,據說有著一個詩人的靈魂。事實上,他吞噬的詩人靈魂早已成千上萬。千百年來,他收集了各式各樣 的靈魂,包括詩人、牧師、帝王、乞丐、奴隸、罪人,當然,還有英雄。每一個靈魂,都有著自己的戰鬥力,而影魔,靠 這些戰鬥力提升自己的攻擊。奈文摩爾有 n 個靈魂,他們在影魔寬廣的體內可以排成一排,從左至右標號 1 到 n。 第 i個靈魂的戰鬥力為 k[i],靈魂們以點對的形式為影魔提供攻擊力,對於靈魂對 i,j(i<j)來說,若不存在 k[s](i <s<j)大於 k[i]或者 k[j],則會為影魔提供 p1 的攻擊力(可理解為:當 j=i+1 時,因為不存在滿足 i<s<j 的 s,從 而 k[s]不存在,這時提供 p1 的攻擊力;當 j>i+1 時,若max{k[s]|i<s<j}<=min{k[i],k[j]} , 則 提 供 p1 的 攻 擊 力 ); 另 一 種 情 況 , 令 c 為k[i+1],k[i+2],k[i+3]......k[j-1]的最大值,若 c 滿足:k[i]<c<k[j],或 者 k[j]<c<k[i],則會為影魔提供 p2 的攻擊力,當這樣的 c 不存在時,自然不會提供這 p2 的攻擊力;其他情況的 點對,均不會為影魔提供攻擊力。影魔的摯友噬魂鬼在一天造訪影魔體內時被這些靈魂吸引住了,他想知道,對於任 意一段區間[a,b],1<=a<b<=n,位於這些區間中的靈魂對會為影魔提供多少攻擊力,即考慮 所有滿足a<=i<j<=b 的靈 魂對 i,j 提供的攻擊力之和。順帶一提,靈魂的戰鬥力組成一個 1 到 n 的排列:k[1],k[2],...,k[n]。Input
Output
共輸出 m 行,每行一個答案,依次對應 m 個詢問。Sample Input
10 5 2 37 9 5 1 3 10 6 8 2 4
1 7
1 9
1 3
5 9
1 5
Sample Output
3039
4
13
16
#include<bits/stdc++.h> #define il inline #define RG register #define ll long long #define db double #define N 200010 #define lowbit (i&-i) using namespace std; int l[N],r[N],st[N],a[N],n,m,p1,p2; ll Ans[N]; namespace BIT{ ll t1[N],t2[N]; void clear(){memset(t1,0,sizeof(t1));memset(t2,0,sizeof(t2));} void add(int x,int y){ for(int i=x;i<=n;i+=lowbit)t1[i]+=y,t2[i]+=1ll*x*y; } void Insert(int l,int r,int num){ add(l,num),add(r+1,-num); } ll Query(int pos){ ll Sum(0); for(int i=pos;i;i-=lowbit)Sum+=(pos+1)*t1[i]-t2[i]; return Sum; } ll sum(int l,int r){ return Query(r)-Query(l-1); } } struct event{ int l,r,h,bel,val; event() {} event(int a,int b,int c,int d,int e):l(a),r(b),h(c),bel(d),val(e) {} }eve1[N*2],eve2[N*3];int tot1,tot2; bool comp(const event & a,const event & b){return a.h<b.h;} int main(){ scanf("%d%d%d%d",&n,&m,&p1,&p2); for(int i=1;i<=n;++i)scanf("%d",&a[i]); for(int i=1;i<=n;++i){ while(st[0]&&a[st[st[0]]]<a[i])r[st[st[0]--]]=i; st[++st[0]]=i; } while(st[0])r[st[st[0]--]]=n+1; for(int i=n;i;i--){ while(st[0]&&a[st[st[0]]]<a[i])l[st[st[0]--]]=i; st[++st[0]]=i; } while(st[0])l[st[st[0]--]]=0; for(int i=1;i<=m;++i){int l,r; scanf("%d%d",&l,&r);Ans[i]+=1ll*(r-l)*p1; eve1[++tot1]=event(l,r,r,i,1); eve1[++tot1]=event(l,r,l-1,i,-1); } sort(eve1+1,eve1+tot1+1,comp); for(int i=1;i<=n;++i){ if(l[i]&&r[i]!=n+1)eve2[++tot2]=event(l[i],l[i],r[i],0,p1); if(l[i]&&r[i]>i+1)eve2[++tot2]=event(i+1,r[i]-1,l[i],0,p2); if(r[i]!=n+1&&l[i]+1<i)eve2[++tot2]=event(l[i]+1,i-1,r[i],0,p2); } sort(eve2+1,eve2+tot2+1,comp); int h1(1),h2(1); while(!eve1[h1].h)h1++; for(int i=1;i<=n&&h1<=tot1;++i){ while(h2<=tot2&&eve2[h2].h==i){ BIT::Insert(eve2[h2].l,eve2[h2].r,eve2[h2].val); h2++; } while(h1<=tot1&&eve1[h1].h==i){ Ans[eve1[h1].bel]+=eve1[h1].val*(BIT::sum(eve1[h1].l,eve1[h1].r)); h1++; } } for(int i=1;i<=m;++i)cout<<Ans[i]<<"\n"; return 0; }
BZOJ4826: [Hnoi2017]影魔