BZOJ 5395--[Ynoi2016]谁的梦(STL&容斥)

5395: [Ynoi2016]谁的梦

Time Limit: 80 Sec  Memory Limit: 128 MB
Submit: 22  Solved: 7
[Submit][Status][Discuss]

Description

6.373
世界是独立于我的意志的。
6.374
就算我们所期望的全部的事情都发生了
这果然也只能说是命运的恩惠吧。
要问为什么,那是因为意志和世界之间
能够保证这件事的逻辑性的关联并不存在
Ludwig Josef Johann Wittgenstein [逻辑哲学论]
自从双胞胎的哥哥过世起,已经过了多久了呢…
从那时起,我一直保存着能够布偶。
在那以后的我只是个影子…而这个布偶才是我…
这样也并没有什么不好。
我觉得只要现在的我消失掉就行了…
那两个人却救了这样的我。
一个是由岐姐…
她又来到了我的身边…
带着皆守哥…回到了我们的身边…
水上由岐姐姐…温柔的姐姐
曾经非常喜欢皆守哥的人……
 
回去的路上…
平时不会经过的坡道…
在登上那个坡道的途中…
我看到了夜晚的太阳。
明明就在附近,却一直不知道的巨大的向日葵。
夜露使它的绒毛泛出了白光。
碧蓝的月光和黄色的向日葵…
就好像太阳和月亮的立场反过来一样…
原本是那么耀眼的太阳在地上,只能在其背后下发光的月亮在天上…
黄色的向日葵被染成了碧蓝色。
那副样子虽然很美丽…
努力绽放的向日葵,看起来反而是柔弱的存在。
在夜里向天空伸展的向日葵…
我在车内一直追寻着它的身影…
被夜晚的月光映照着的太阳。
被染成碧蓝色的太阳…
它的身影…我一直追寻着……
 
被月光照亮的天台上…
一个人影…
明明只是一个人影…却好像…在和什么东西对峙着一样…
皆守哥…
月下的立像,一个人影。
胸口在风中闪烁。
放在胸前的手里的是…那时的小刀。
和七年前同样的姿势。
唯一不同的是,那里的人影只有一个。
那把小刀,好像是被他自己刺入体内。
 
是诅咒…
这是理所当然的事…
那并不是什么精神病…
那是诅咒…
下在幸存的我们身上的…诅咒…
说不定,不仅仅是卓司哥…连由岐姐也在诅咒我们…
所以变成这种结果…
哥哥刺向了自己的胸口…
破坏了我的半身…
然后…还要把很多人送回到天空…
回归天空的日子。
交还灵魂的日子。
那一天,卓司哥对我做的事情。
杀了由岐姐的…那个行为…
他想要再一次实行…
这次…和很多人一起…
 
不是…
那是…我啊…
是那个…坡道的事情啊…
两个人一起看到向日葵的…那个坡道…
…我说要爬上那个坡道…要去寻找爸爸的灵魂…
我想,如果到了那个坡道的前方,就能取回爸爸的灵魂…爸爸就会复生的…
如果越过向日葵之路…向着向日葵所朝向的天空延伸的…那个大大的坡道的话…大概,就会有爸爸的灵魂…
爸爸的故乡的…大大的坡道…
 
哥哥的身体浮在空中…
我无言地跳了出去。
啊啊…是这样啊…
由岐姐也是这种心情啊…
并没有什么道理可言…
只是因为喜欢的人向着天空跳下去了…
我想要抓住那个身体…
我--
您正在打galgame,突然断电了,于是您跑去物管处问,结果发现是由于一个光头踢了变压器一脚导致的,
可能还要修很久,于是您决定想一个之前见过的数据结构题:
定义一个序列的权值为不同数字的个数,例如 [1,2,3,3] 权值为 3
现在有n个序列,我们在每个序列里面选一个连续非空子串,拼接起来,求所有选法得到的序列的权值之和
如果一个序列能通过多种方法被选择出来,那么计算多次
本题带修改操作,格式请参考输入格式
由于结果可能过大,请输出答案 mod 19260817 的结果

 

Input

第一行两个数 n,m,表示有n个序列,m次修改
然后n个数,第i个数是leni,表示第i个序列的长度
之后n行,每行leni个数,表示第i个序列
之后m行,每行三个数x,y,z表示将第x个序列的第y个元素改为z
1 <= n,m <= 100000,序列中的元素均为 32 位整型数,leni的和 <= 100000
共53组数据

 

Output

输出m + 1行,依次表示初始局面以及每次修改后的答案。

 

Sample Input

2 5
6 6
1 3 1 1 3 2
2 3 3 2 1 1
1 1 1
1 1 2
1 1 2
1 1 1
1 1 1

Sample Output

1158
1158
1168
1168
1158
1158
 

题目链接:

    http://www.lydsy.com/JudgeOnline/problem.php?id=5395 

Solution

  少女的等待故事。

  爱慕哥哥的少女,她坚信着哥哥的承诺,在向日葵的坡道下等待着他的回归。

  居然在ynoi上抢到rk1.。。感觉很神奇。。。果然是因为我是素学家吗QAQ

  

  然后是题解。。。

  首先发现每种颜色对答案的贡献都是独立的。。。

  对于某一种颜色,直接算在多少个序列中出现比较困难。。

  所以考虑用总数减去没有出现的次数。。

  然后对每一行统计答案,然后乘法原理。。。遍历的时候要用set。。。

  单点修改只会影响某两种颜色的贡献,暴力修改即可。。

代码

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#define LL long long
using namespace std;
inline int read(){
    LL x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline void Out(LL a){
    if(a>9) Out(a/10);
    putchar(a%10+'0');
}
const LL N=200050;
const LL mod=19260817;
LL n,m,tot,num,LEN,NY;
LL a[N],hang[N],lie[N],len[N],hed[N];
LL sum[N],nsum[N],ans[N],zer[N];
set<LL> S[N];
map<LL,LL>lsh;
map<LL,LL> mp[N],c[N];
LL res=0,ss;
LL pow(LL x,LL y){
    LL re=1;
    while(y){
        if(y&1) re=re*x%mod;
        x=x*x%mod;y>>=1;
    }
    return re;
}
LL get(LL u,LL v){
    LL l=1,r=tot;
    while(l!=r){
        LL mid=l+r>>1;
        if(hang[mid]<u||(hang[mid]==u&&lie[mid]<v)) l=mid+1;
        else r=mid;
    }
    return l;
}
int main(){
    NY=pow((LL)2,mod-2);
    n=read();m=read();ss=1;
    for(LL i=1;i<=n;++i){
        len[i]=read();
        ss=ss*(LL)len[i]%mod*(LL)(len[i]+1)%mod*NY%mod;
        LEN+=len[i];
    }
    //cout<<ss<<endl; 
    sum[0]=nsum[0]=1;
    for(LL i=1;i<=n;++i){
        sum[i]=(LL)(len[i]+1)*(LL)len[i]/(LL)2%mod;
        sum[i]=sum[i]*sum[i-1]%mod;
        nsum[i]=pow(sum[i],mod-2);
        for(LL j=1;j<=len[i];++j){
            a[++tot]=read();
            if(!lsh[a[tot]]) {
                lsh[a[tot]]=++num;
            }
            a[tot]=lsh[a[tot]];
            S[a[tot]].insert(tot);
            hang[tot]=i;lie[tot]=j;
        }
    }
    LL u,v,w,x;
    for(LL i=1;i<=num;++i){
        u=0;v=0;ans[i]=1;
        for(set<LL>::iterator it=S[i].begin();it!=S[i].end();++it){
            //cout<<u<<" "<<v<<endl;
            x=*it;
            if(u==0){
                ans[i]=ans[i]*sum[hang[x]-1]%mod;
                mp[i][hang[x]]+=(LL)(lie[x]-1)*(LL)lie[x]/(LL)2;
            }
            else if(u!=hang[x]){
                mp[i][u]+=(LL)(len[u]-v)*(LL)(len[u]-v+1)/(LL)2;
                if(mp[i][u]>0) ans[i]=ans[i]*mp[i][u]%mod;
                else zer[i]++;
                ans[i]=ans[i]*sum[hang[x]-1]%mod*nsum[u]%mod;
                mp[i][hang[x]]+=(LL)(lie[x]-1)*(LL)lie[x]/(LL)2;
            }
            else mp[i][hang[x]]+=(LL)(lie[x]-v-1)*(LL)(lie[x]-v)/2;
            u=hang[x];v=lie[x];
        }
        mp[i][u]+=(LL)(len[u]-v)*(LL)(len[u]-v+1)/(LL)2;
        if(mp[i][u]>0) ans[i]=ans[i]*mp[i][u]%mod;
        else zer[i]++;
        ans[i]=ans[i]*sum[n]%mod*nsum[u]%mod;
        if(zer[i]>0) res+=ss;
        else res+=ss-ans[i];
        //cout<<ss<<" "<<ans[i]<<endl;
    }
    res=(res%mod+mod)%mod;
    Out(res);puts("");
    set<LL>::iterator l,r;
    LL L,R,lx,rx;
    while(m--){
        u=read();v=read();w=read();
        x=get(u,v);
        l=S[a[x]].lower_bound(x);
        r=l;
        if(l==S[a[x]].begin()) L=0;
        else {
            --l;L=*l;
            if(hang[L]!=u) L=0;
            else L=lie[L];
        }
        ++r;
        if(r==S[a[x]].end()) R=len[u];
        else{
            R=(*r);
            if(hang[R]!=u) R=len[u];
            else R=lie[R]-1;
        }
        if(zer[a[x]]>0) res-=ss;
        else res-=ss-ans[a[x]];
        if(mp[a[x]][u]>0)ans[a[x]]=ans[a[x]]*pow(mp[a[x]][u],mod-2)%mod;
        else --zer[a[x]];
        mp[a[x]][u]-=(LL)(R-v)*(R-v+1)/2+(LL)(v-1-L)*(v-L)/2;
        mp[a[x]][u]+=(LL)(R-L)*(R-L+1)/2;
        if(mp[a[x]][u]>0) ans[a[x]]=ans[a[x]]*mp[a[x]][u]%mod;
        else ++zer[a[x]];
        if(zer[a[x]]>0) res+=ss;
        else res+=ss-ans[a[x]];
        S[a[x]].erase(x);
        if(!lsh[w]){
            lsh[w]=++num;
            ans[num]=sum[n];
        }
        w=lsh[w];
        a[x]=w;
        S[w].insert(x);
        l=S[a[x]].lower_bound(x);
        r=l;
        if(l==S[a[x]].begin()) L=0;
        else {
            --l;L=*l;
            if(hang[L]!=u) L=0;
            else L=lie[L];
        }
        ++r;
        if(r==S[a[x]].end()) R=len[u];
        else{
            R=(*r);
            if(hang[R]!=u) R=len[u];
            else R=lie[R]-1;
        }
        if(R==len[u]&&L==0) mp[w][u]=(LL)(len[u]+1)*(LL)len[u]/2;
        if(zer[a[x]]>0) res-=ss;
        else res-=ss-ans[a[x]];
        if(mp[a[x]][u]>0)ans[a[x]]=ans[a[x]]*pow(mp[a[x]][u],mod-2)%mod;
        else --zer[a[x]];
        mp[a[x]][u]-=(LL)(R-L)*(R-L+1)/2;
        mp[a[x]][u]+=(LL)(R-v)*(R-v+1)/2+(LL)(v-1-L)*(v-L)/2;
        if(mp[a[x]][u]>0) ans[a[x]]=ans[a[x]]*mp[a[x]][u]%mod;
        else ++zer[a[x]];
        if(zer[a[x]]>0) res+=ss;
        else res+=ss-ans[a[x]];
        res=(res%mod+mod)%mod;
        Out(res);puts("");
    }
    return 0;
}

  

  

This passage is made by Iscream-2001.

 

posted @ 2018-09-15 20:04  Iscream-2001  阅读(156)  评论(0编辑  收藏