思路:
等比数列求和 (无穷项)
+线段树找逆序对
//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 ",ans); }