zoukankan      html  css  js  c++  java
  • P4692 [Ynoi2016]谁的梦

    传送门

    分别考虑每一种颜色对答案的贡献。每种颜色的贡献就是他出现的区间个数,那么可以用总区间减去不包含它的区间个数,把每一个序列里不包含它的区间个数加起来,然后不同序列用乘法原理计算即可

    于是我辛辛苦苦打了两个小时交上去只剩两分……后来看了题解之后才发现我忘了考虑某个序列全都是一个数的情况……那种情况下这个数贡献为0,然而后面删除它的时候没办法消除贡献因为0没有逆元……

    于是解决方法就是记录一下这个数字是否在某个序列里全都是,如果是的话不包含它的区间为0,否则的话正常计算就可以了

    然后代码里是一些丧心病狂的卡常……抄了iscream巨巨的题解还不小心抢了他的rank1心里有点莫名其妙的羞愧→_→

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #define IT set<int>::iterator
    #define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
    #define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    using namespace std;
    char buf[1<<21],*p1=buf,*p2=buf;
    inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    int read(){
        R int res,f=1;R char ch;
        while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    char sr[1<<21],z[20];int C=-1,Z=0;
    inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    void print(R int x){
        if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
        while(z[++Z]=x%10+48,x/=10);
        while(sr[++C]=z[Z],--Z);sr[++C]='
    ';
    }
    const int N=2e5+5,P=19260817;
    inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
    inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
    inline int calc(R int l){return 1ll*l*(l+1)/2%P;}
    int ksm(R int x,R int y){
        R int res=1;
        for(;y;y>>=1,x=1ll*x*x%P)if(y&1)res=1ll*res*x%P;
        return res;
    }
    set<int>s[N];map<int,int>mp[N];
    int len[N],sum[N],isum[N],inv[N],sl[N],zero[N];
    int a[N],b[N],x[N],y[N],d[N],hang[N],lie[N],nxt[N],head[N],ans[N];
    int n,m,tot,lim,all,loli;
    inline int Inv(R int x){return x<=2e5?inv[x]:ksm(x,P-2);}
    void solve(int x,int y,int d){
    	int id=sl[x-1]+y,l=0,r=len[x]+1,col=a[id];
    	IT itl,itr;itl=s[col].lower_bound(id),itr=itl;
    	if(itl!=s[col].begin()){
    		--itl;if(hang[*itl]==x)l=lie[*itl];
    	}
    	++itr;if(itr!=s[col].end()&&hang[*itr]==x)r=lie[*itr];
    	loli=dec(loli,zero[col]?all:dec(all,ans[col]));
    	if(mp[col][x]>0)ans[col]=1ll*ans[col]*Inv(mp[col][x])%P;
    	else --zero[col];
    	mp[col][x]=dec(mp[col][x],add(calc(r-y-1),calc(y-l-1)));
    	mp[col][x]=add(mp[col][x],calc(r-l-1));
    	if(mp[col][x]>0)ans[col]=1ll*ans[col]*mp[col][x]%P;
    	else ++zero[col];
    	loli=add(loli,zero[col]?all:dec(all,ans[col]));
    	s[col].erase(id);
    	
    	l=0,r=len[x]+1,a[id]=d,col=d,s[col].insert(id);
    	itl=s[col].lower_bound(id),itr=itl;
    	if(itl!=s[col].begin()){
    		--itl;if(hang[*itl]==x)l=lie[*itl];
    	}
    	++itr;if(itr!=s[col].end()&&hang[*itr]==x)r=lie[*itr];
    	if(r==len[x]+1&&l==0)mp[col][x]=calc(len[x]);
    	loli=dec(loli,zero[col]?all:dec(all,ans[col]));
    	if(mp[col][x]>0)ans[col]=1ll*ans[col]*Inv(mp[col][x])%P;
    	else --zero[col];
    	mp[col][x]=dec(mp[col][x],calc(r-l-1));
    	mp[col][x]=add(mp[col][x],add(calc(r-y-1),calc(y-l-1)));
    	if(mp[col][x]>0)ans[col]=1ll*ans[col]*mp[col][x]%P;
    	else ++zero[col];
    	loli=add(loli,zero[col]?all:dec(all,ans[col]));
    	print(loli);
    }
    int main(){
    //	freopen("testdata.in","r",stdin);
        inv[0]=inv[1]=1;for(int i=2;i<=2e5;++i)inv[i]=((-(1ll*P/i)*inv[P%i])%P+P)%P;
    	n=read(),m=read(),sum[0]=isum[0]=1,tot=0;
    	fp(i,1,n){
    		len[i]=read(),sl[i]=sl[i-1]+len[i];
    		sum[i]=1ll*calc(len[i])*sum[i-1]%P,isum[i]=Inv(sum[i]);
    	}all=sum[n];
    	fp(i,1,n)fp(j,1,len[i])b[++lim]=a[++tot]=read(),hang[tot]=i,lie[tot]=j;
    	fp(i,1,m)x[i]=read(),y[i]=read(),b[++lim]=d[i]=read();
    	sort(b+1,b+1+lim),lim=unique(b+1,b+1+lim)-b-1;
    	tot=0;fp(i,1,n)fp(j,1,len[i]){
    		++tot,a[tot]=lower_bound(b+1,b+1+lim,a[tot])-b;
    		s[a[tot]].insert(tot);
    	}fd(i,tot,1)nxt[i]=head[a[i]],head[a[i]]=i;
    	fp(i,1,m)d[i]=lower_bound(b+1,b+1+lim,d[i])-b;
    	fp(i,1,lim)if(head[i]){
    		ans[i]=sum[hang[head[i]]-1];
    		for(R int j=head[i];j;j=nxt[j]){
    			int bl=hang[j],res=0,las=sl[bl-1];
    			while(hang[nxt[j]]==bl)res=add(res,calc(j-las-1)),las=j,j=nxt[j];
    			res=add(res,calc(j-las-1)),res=add(res,calc(sl[bl]-j));
    			if(res)ans[i]=1ll*ans[i]*res%P,mp[i][bl]=res;
    			else ++zero[i];
    			if(!nxt[j])ans[i]=1ll*ans[i]*sum[n]%P*isum[bl]%P;
    			else ans[i]=1ll*ans[i]*sum[hang[nxt[j]]-1]%P*isum[bl]%P;
    		}loli=add(loli,zero[i]?all:dec(all,ans[i]));
    	}else ans[i]=sum[n];
    	print(loli);fp(i,1,m)solve(x[i],y[i],d[i]);return Ot(),0;
    }
    
  • 相关阅读:
    Android 开发 深入理解Handler、Looper、Messagequeue 转载
    Android 开发 Handler的基本使用
    Java 学习 注解
    Android 开发 AlarmManager 定时器
    Android 开发 框架系列 百度语音合成
    Android 开发 框架系列 Google的ORM框架 Room
    Android 开发 VectorDrawable 矢量图 (三)矢量图动画
    Android 开发 VectorDrawable 矢量图 (二)了解矢量图属性与绘制
    Android 开发 VectorDrawable 矢量图 (一)了解Android矢量图与获取矢量图
    Android 开发 知晓各种id信息 获取线程ID、activityID、内核ID
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10150887.html
Copyright © 2011-2022 走看看