BZOJ 4481

思路:

等比数列求和 (无穷项)

+线段树找逆序对

//By SiriusRen
#include <bits/stdc++.h>
const int N=500500;
int n,m,vis[N],now=1;
double p,r[N],tree[N*8],ans;
struct Node{int x,y;}node[N];
bool cmp(Node a,Node b){if(a.x!=b.x)return a.x<b.x;return a.y<b.y;}
void insert(int l,int r,int pos,int num,double wei){
    if(l==r){tree[pos]+=wei;return;}
    int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
    if(mid<num)insert(mid+1,r,rson,num,wei);
    else insert(l,mid,lson,num,wei);
    tree[pos]=tree[lson]+tree[rson];
}
double query(int l,int r,int pos,int L,int R){
    if(L>R)return 0;
    if(l>=L&&r<=R)return tree[pos];
    int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
    if(mid<L)return query(mid+1,r,rson,L,R);
    else if(mid>=R)return query(l,mid,lson,L,R);
    else return query(l,mid,lson,L,R)+query(mid+1,r,rson,L,R);
}
double w(int now,int t){return p*r[t-1]/(1-r[vis[node[now].x]]);}
int main(){
    scanf("%d%d%lf",&n,&m,&p),r[0]=1;
    for(int i=1;i<=500000;i++)r[i]=r[i-1]*(1-p);
    for(int i=1;i<=m;i++)scanf("%d%d",&node[i].x,&node[i].y),vis[node[i].x]++;
    std::sort(node+1,node+1+m,cmp);
    for(int i=1,t=0;i<=n;i++,t=0)while(node[now].x==i)
        t++,insert(1,n,1,node[now].y,w(now,t)),
        ans+=w(now,t)*query(1,n,1,node[now].y+1,n),now++;
    printf("%.2f\n",ans);
}

 

posted @ 2017-05-30 10:44  SiriusRen  阅读(326)  评论(0编辑  收藏  举报