zoukankan      html  css  js  c++  java
  • [51nod2014] 小朋友的笑话

    问题描述

    小O是一个很萌很萌的女孩子。
    有一天小O叫了很多很多萌萌哒小朋友到家里来玩。
    由于太无聊了,她们开始讲笑话。
    总共有N个小朋友排成一排,编号1~N。
    在某个时刻,会有编号为xi的小朋友看到了笑话li,然后她会把这个笑话讲出来,与她距离不超过ki的小朋友都会听到这个笑话。
    当一个小朋友听到一个笑话时,如果她是第一次听得到这个笑话,那么她会觉得这个笑话非常好笑,笑的停不下来。如果她听到之前就是在笑的她会继续笑。
    如果她之前听过这个笑话,那么她会觉得这个笑话非常无聊,她会立即停止笑。

    现在小O想知道,在某些时刻一段区间内有多少小朋友在笑。

    输入格式

    第一行两个整数N,M,表示小朋友的数量和事件数量,(1<=N,M<=100000)
    接下来M行
    第一行为一个正整数op(1<=op<=2),表示事件类型。
    如果op=1,接下来三个整数xi li ki,表示该时间点小朋友xi(1<=xi<=N)讲了一个笑话li(1<=li<=100000),传播距离为ki(0<=ki<=N)。
    如果op=2,接下来两个整数l r,表示该时间点小O想知道区间[l,r]中有多少小朋友在笑(1<=l<=r<=N)

    输出格式

    对每个询问操作,输出答案

    样例输入

    10 14
    1 3 11 0
    2 3 3
    1 3 11 2
    2 1 5
    1 5 12 1
    2 4 6
    1 8 13 2
    2 6 10
    1 7 11 2
    2 5 9
    1 10 12 1
    2 9 10
    1 9 12 0
    2 1 10

    样例输出

    1
    4
    3
    5
    4
    2
    7

    解析

    最关键的一点是如何处理某个笑话在某个点是否重复出现过。

    单独考虑某一个笑话,问题就转化为区间覆盖,求哪些位置是第一次被覆盖。考虑用set维护所有区间,第一关键字为左端点。对于当前要插入的区间[l,r],我们可以利用 lower_bound很方便的求出所有与这个区间有交集的区间。我们先把[l,r]都标记为在笑,然后依次扫描刚才找到的有交集的区间,把交集部分标记为没在笑。最后再向set中插入这个区间。这样的修改和查询都可以用线段树解决。

    但是这样的时间复杂度不能保证。所以,每次我们都要把上面扫描到的区间以及当前区间都合并成一个区间。这样,每个区间都只会插入、修改、合并一次。这样就可以通过了。

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #define int long long
    #define N 202
    using namespace std;
    const int mod=1000000007;
    struct card{
    	int a,g,p,id;
    }a[N*N];
    int n,m[N],v[N],cnt,i,j,f[N],ans[N],p[N];
    int read()
    {
    	char c=getchar();
    	int w=0;
    	while(c<'0'||c>'9') c=getchar();
    	while(c<='9'&&c>='0'){
    		w=w*10+c-'0';
    		c=getchar();
    	}
    	return w;
    }
    int poww(int a,int b)
    {
    	int ans=1,base=a;
    	while(b){
    		if(b&1) ans=ans*base%mod;
    		base=base*base%mod;
    		b>>=1;
    	}
    	return ans;
    }
    int my_comp(const card &x,const card &y)
    {
    	return x.a>y.a;
    }
    signed main()
    {
    	n=read();
    	for(i=1;i<=n;i++){
    		m[i]=read();
    		int inv=0;
    		for(j=1;j<=m[i];j++){
    			cnt++;
    			a[cnt].a=read(),a[cnt].g=read(),a[cnt].p=read();
    			a[cnt].id=i;
    			a[cnt].g=(100-a[cnt].g)*poww(100,mod-2)%mod;
    			inv=(inv+a[cnt].p)%mod;
    		}
    		inv=poww(inv,mod-2);
    		for(j=1;j<=m[i];j++) a[cnt-j+1].p=a[cnt-j+1].p*inv%mod;
    	}
    	for(i=1;i<=n;i++) v[i]=read();
    	sort(a+1,a+cnt+1,my_comp);
    	f[1]=1;
    	for(i=1;i<=cnt;i++){
    		if(a[i-1].id!=a[i].id){
    			int inv=poww(1-p[a[i].id]+mod,mod-2);
    			f[1]=f[1]*inv%mod;
    			for(j=2;j<=n;j++) f[j]=(f[j]-f[j-1]*p[a[i].id]%mod+mod)%mod*inv%mod;
    			for(j=n;j>=1;j--) f[j]=(f[j]*(1-p[a[i-1].id]+mod)%mod+f[j-1]*p[a[i-1].id]%mod)%mod;
    		}
    		for(j=1;j<=n;j++) ans[a[i].id]=(ans[a[i].id]+f[j]*v[j]%mod*a[i].p%mod*a[i].g%mod)%mod;
    		p[a[i].id]=(p[a[i].id]+a[i].p)%mod;
    	}
    	for(i=1;i<=n;i++) printf("%lld
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    Lambda表达式、依赖倒置
    ASP.NET vNext 概述
    Uname
    RHEL4 i386下安装rdesktop【原创】
    Taxonomy of class loader problems encountered when using Jakarta Commons Logging(转)
    How to decompile class file in Java and Eclipse
    先有的资源,能看的速度看,不能看的,抽时间看。说不定那天就真的打不开了(转)
    Google App Engine 学习和实践
    【VBA研究】VBA通过HTTP协议实现邮件轨迹跟踪查询
    js正則表達式语法
  • 原文地址:https://www.cnblogs.com/LSlzf/p/12616696.html
Copyright © 2011-2022 走看看