標籤:highlight class add algorithm font string 有一個 return ios
MooFest 狂歡節 bzoj-3378 Usaco-2004 Open
題目大意:給定一個n個數的a序列,每兩個數之間有一個距離,兩個點之間的權值為$max(a[i],a[j])*dis(i,j)$。
注釋:$1\le n\le 2\cdot 10^4$。
想法:裙子說了,這種$max$和$min$的題通常要枚舉這個$max$和$min$到底是多少。
這樣的話我們就將所有點按權值從大到小排序。
往樹狀數組裡插。
查詢直接查詢即可。
最後,附上醜陋的代碼... ...
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm> using namespace std;const int N=20000;int n,num[N+5],cnt;long long sum[N+5],ans,tot;struct Node{int v,x;}a[N+5]; bool cmp(const Node &x,const Node &y){return x.v>y.v;}inline int lowbit(int x) {return x&(-x);}void add(int x,int v,int k){ for(int i=x;i<=N;i+=lowbit(i)) sum[i]+=v,num[i]+=k;}void query(int x){ for(int i=x;i>0;i-=lowbit(i)) tot+=sum[i],cnt+=num[i];}void work(){ for(int i=1;i<=n;i++){ tot=cnt=0; query(a[i].x); ans+=a[i].v*(cnt*a[i].x-tot); cnt=-cnt,tot=-tot; query(N); ans+=a[i].v*(tot-cnt*a[i].x); add(a[i].x,-a[i].x,-1); } cout << ans << endl ;}void init(){ cin >> n ; for(int i=1;i<=n;i++) scanf("%d%d",&a[i].v,&a[i].x); sort(a+1,a+1+n,cmp); for(int i=1;i<=n;i++) add(a[i].x,a[i].x,1);}int main(){ init(); work(); return 0;}
小結:裙子有時候想法好$nb$啊!%%%
[bzoj3378][Usaco2004 Open]MooFest 狂歡節_樹狀數組