1. 程式人生 > >bzoj 5055: 膜法師

bzoj 5055: 膜法師

這題膜地也太暴力了吧
話說我天天刷水題是不是沒救了(躺

感覺上 用DP來算(其實我也不知道是不是DP) 怎麼做就很明顯了吧
一個數作為中間數的答案和就是 前面比它小的和 跟它乘起來
一個數作為後面數的答案和就是 前面比它小的 作為中間數的答案和 跟它乘起來

既然不能簡單粗暴地n^2算 那就排序一下 用樹狀陣列來算兩次就好

#include<bits/stdc++.h>
using namespace std;
const int mod=19260817,N=300005;
char B[1<<14],*S=B,*T=B;
#define g (S==T&&(T=(S=B)+fread(B,1,1<<14,stdin),S==T)?-1:*S++)
inline int read(){ int x=0,f=1; char ch=g; while(ch<'0' || ch>'9'){if(ch=='-')f=-1; ch=g;} while(ch>='0' && ch<='9'){x=(x<<1)+(x<<3)+ch-'0'; ch=g;} return x*f; } struct P{int x,y;}a[N]; int b[N],c[N],t[N],n; int Cmp(P x1,P x2){ return x1.x!=x2.x?x1.x<x2.x
:x1.y>x2.y; } void add(int x,int u){for(;x<=n;x+=x&-x)t[x]=(t[x]+u)%mod;} int get(int x){int u=0; for(;x;x-=x&-x)u=(u+t[x])%mod; return u;} int main(){ n=read(); int i; for(i=1;i<=n;++i)a[i].x=read()%mod,a[i].y=i; sort(a+1,a+1+n,Cmp); for(i=1;i<=n;++i) b[i]=1
ll*get(a[i].y)*a[i].x%mod,add(a[i].y,a[i].x); for(i=1;i<=n;++i)t[i]=0; int ans=0; for(i=1;i<=n;++i) c[i]=1ll*get(a[i].y)*a[i].x%mod,ans=(ans+c[i])%mod,add(a[i].y,b[i]); printf("%d\n",ans); return 0; }