竞赛讨论区 > E题题解
头像
zlc1114
编辑于 2018-07-29 01:18
+ 关注

E题题解

E。。其实是个简单题啊。。就是题意很坑,我看错好几次
E题意是:给你一堆点,然后每个点有出现的概率
然后对于出现的每个点集,定义F(s)是它左下(也就是那个台阶形状)的面积,也就是有 i 满足 0 < x ≤ xi and 0 < y ≤ yi 的(x,y)点数,问你那个面积的期望
做法是:线段树+扫描线就完了,是个板子题
考虑到,每个点会被计入答案当且仅当右上方没有点出现过
也就是。。1-乘法{1-右上点出现点的概率}

所以,你只需要倒着排下序,然后扫描线维护每一段 x 的 所有 y(1到某个值)的 乘法{1-右上点出现点的概率} 总和 就完事了
具体就是。。对于一段连续的 y,一定值(概率)是一样的,所以你定义线段树上的每个位置是这个点向前的一段就行

这个东西扫描线就很好搞了。。我觉得已经足够明显,怎么实现留给读者去做

#include <sstream>
#include <fstream>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <cstring>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <utility>
#include <cassert>
#include <bitset>
using namespace std;
#define REP(I,N) for (I=0;I<N;I++)
#define rREP(I,N) for (I=N-1;I>=0;I--)
#define rep(I,S,N) for (I=S;I<N;I++)
#define rrep(I,S,N) for (I=N-1;I>=S;I--)
#define FOR(I,S,N) for (I=S;I<=N;I++)
#define rFOR(I,S,N) for (I=N;I>=S;I--)

#define DEBUG
#ifdef DEBUG
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define deputs(str) fprintf(stderr, "%s\n",str)
#else
#define debug(...)
#define deputs(str)
#endif // DEBUG
typedef unsigned long long ULL;
typedef unsigned long long ull;
typedef long long LL;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
const int INF=0x3f3f3f3f;
const LL INFF=0x3f3f3f3f3f3f3f3fll;
const LL M=1e9+7;
const LL maxn=1e5+7;
const double pi=acos(-1.0);
const double eps=0.0000000001;
LL gcd(LL a, LL b) {return b?gcd(b,a%b):a;}
template<typename T>inline void pr2(T x,int k=64) {ll i; REP(i,k) debug("%d",(x>>i)&1); putchar(' ');}
template<typename T>inline void add_(T &A,int B) {A+=B; (A>=M) &&(A-=M);}
template<typename T>inline void mul_(T &A,ll B) {A=(A*B)%M;}
template<typename T>inline void mod_(T &A,ll B=M) {A%=M; A+=M; A%=M;}
template<typename T>inline void max_(T &A,T B) {(A<B) &&(A=B);}
template<typename T>inline void min_(T &A,T B) {(A>B) &&(A=B);}
template<typename T>inline T abs(T a) {return a>0?a:-a;}
template<typename T>inline T powMM(T a, T b) {
    T ret=1;
    for (; b; b>>=1ll,a=(LL)a*a%M)
        if (b&1) ret=(LL)ret*a%M;
    return ret;
}
int n,m,q;
char str[maxn];
int TaskA();
void Task_one() {TaskA();}
void Task_T() {int T; scanf("%d",&T); while (T--) TaskA();}
void Task_more_n() {while (~scanf("%d",&n)) TaskA();}
void Task_more_n_m() {while (~scanf("%d%d",&n,&m)) TaskA();}
void Task_more_n_m_q() {while (~scanf("%d%d%d",&n,&m,&q)) TaskA();}
void Task_more_string() {while (~scanf("%s",str)) TaskA();}

vector<int> V;
int sum[maxn*4],lazy[maxn*4];//val:exist
void build(int x,int L,int R) {
    lazy[x]=1;
    if (L==R) {sum[x]=V[R]-V[R-1]; return;}
    int mid=(L+R)/2;
    build(x<<1,L,mid);
    build(x<<1|1,mid+1,R);
    sum[x]=(sum[x<<1]+sum[x<<1|1])%M;
}
void change(int x,int val) {
    mul_(sum[x],val); mul_(lazy[x],val);
}
void pushdown(int x) {
    if (lazy[x]!=1) {
        change(x<<1,lazy[x]);
        change(x<<1|1,lazy[x]);
        lazy[x]=1;
    }
}
void update(int x,int l,int r,int val,int L,int R) {
    if (l<=L&&R<=r) {change(x,val); return;};
    int mid=(L+R)/2;
    pushdown(x);
    if (l<=mid) update(x<<1,l,r,val,L,mid);
    if (mid<r) update(x<<1|1,l,r,val,mid+1,R);
    sum[x]=(sum[x<<1]+sum[x<<1|1])%M;
}
struct node {
    int x,y,p;
    node(int x=0,int y=0,int p=1):x(x),y(y),p(p) {};
} P[maxn];
vector<node> Points;
int TaskA() {
    int i;
    scanf("%d",&n);
    V.clear();
    FOR(i,1,n) {
        int x,y,p,q;
        scanf("%d%d%d%d",&x,&y,&p,&q);
        V.push_back(y);
        P[i]=node(x,y,(ll)p*powMM((ll)q,M-2)%M);
    } sort(P+1,P+1+n,[](node A,node B) {
        if (A.x!=B.x) return A.x>B.x;
        if (A.y!=B.y) return A.y>B.y;
        return A.p<B.p;
    }); P[n+1].x=0;
    V.push_back(0); sort(V.begin(),V.end());
    V.erase(unique(V.begin(),V.end()),V.end());
    FOR(i,1,n) P[i].y=lower_bound(V.begin(),V.end(),P[i].y)-V.begin();
    ll ans=0; int N=V.size()-1;
    build(1,1,N);
    FOR(i,1,n) {
        Points.push_back(P[i]);
        if (P[i].x!=P[i+1].x) {
            for (auto now:Points) update(1,1,now.y,(M+1-now.p)%M,1,N);
            ans+=(ll)(P[i].x-P[i+1].x)*(V[V.size()-1]-sum[1])%M;
            Points.clear();
        }
    } mod_(ans);
    printf("%lld\n",ans);
    return 0;
}
void initialize() {}
int main() {
    int startTime=clock();
    //initialize
    initialize();
    debug("/--- initializeTime: %ld milliseconds ---/\n",clock()-startTime);
    Task_T();
}
/*
*/

全部评论

(0) 回帖
加载中...
话题 回帖

等你来战

查看全部

热门推荐