省选模拟赛Round1Day2 旅游 宝石([CTS2019]珍珠) 线段([APIO2019]路灯)

 

省选模拟赛Round1Day2 旅游 宝石([CTS2019]珍珠) 线段([APIO2019]路灯)_第1张图片

拆开高斯函数后,动态开点线段树优化DP

啊啊啊啊为什么只有50分

淦,没有把线段树的mx值赋成-INF。。。

代码:

#include
#include
#include
using namespace std;
inline int gi()
{
	char c;int num=0,flg=1;
	while((c=getchar())<'0'||c>'9')if(c=='-')flg=-1;
	while(c>='0'&&c<='9'){num=num*10+c-48;c=getchar();}
	return num*flg;
}
#define N 222222
#define LOG 30
#define LL long long
const LL INF=0x3f3f3f3f3f3f3f3fll;
int c[N],x,y,z,A,m[N];
LL f[N];
struct node{
	int l,r;LL x;
}a[N*LOG];
int rt,tot;
void insert(int &i,int l,int r,int x,LL k)
{
	if(!i)i=++tot,a[i].x=-INF;
	a[i].x=max(a[i].x,k);
	if(l==r)return;
	int mid=(l+r)>>1;
	if(x<=mid)insert(a[i].l,l,mid,x,k);
	else insert(a[i].r,mid+1,r,x,k);
}
LL query(int i,int l,int r,int ql,int qr)
{
	if(!i||l>qr||r>1;
	return max(query(a[i].l,l,mid,ql,qr),query(a[i].r,mid+1,r,ql,qr));
}
struct anode{
	int c,m;
	bool operator == (const anode &t)const{
		return c==t.c;
	}
}tmp[N];
int main()
{
	freopen("tourist.in","r",stdin);
	freopen("tourist.out","w",stdout);
	int n,i;
	x=gi();y=gi();z=gi();A=gi();n=gi();
	tmp[1].c=x;tmp[n+2].c=y;
	for(i=2;i<=n+1;i++){tmp[i].c=gi();tmp[i].m=gi();}
	n=n+2;
	if(tmp[n]==tmp[n-1])n--;
	if(tmp[1]==tmp[2]){for(i=1;i

 

省选模拟赛Round1Day2 旅游 宝石([CTS2019]珍珠) 线段([APIO2019]路灯)_第2张图片

 

题解:生成函数

每个珠子都要选择一种颜色,当一种颜色的珠子有k个时,这种颜色就可以贡献floor(k/2)个袋子

设有A种颜色拥有奇数颗珠子,这些珠子的个数为x

那么总袋子数就为(n-x)/2+(x-A)/2>=m

化一下可得n-2*m>=A  (A<=D)

一种颜色有奇数k颗珠子选择它的方案数为C(n,k)=n!/(k!*(n-k)!)

我们选择指数型生成函数来解决这个问题

(这个问题本质上就是把每个珠子分配一种颜色,再将相同颜色的去重,其实就是可重集的全排列)

那么一种颜色的指数生成函数就是e^x

一种只有奇数个球的颜色的指数生成函数就是\frac{e^x-e^{-x}}{2}

省选模拟赛Round1Day2 旅游 宝石([CTS2019]珍珠) 线段([APIO2019]路灯)_第3张图片

 

代码:(注意一下二项式反演的部分)

#include
#include
#include
using namespace std;
#define N 300005
const int mod=998244353;
const int inv2=499122177;
int fac[N],finv[N];
int wl,wn[N],rev[N];
int ksm(int x,int y)
{
	int ret=1;x=(x%mod+mod)%mod;
	while(y){
		if(y&1)ret=1ll*ret*x%mod;
		y>>=1;x=1ll*x*x%mod;
	}
	return ret;
}
void shai()
{
	int i,n=100000;
	fac[0]=fac[1]=finv[0]=finv[1]=1;
	for(i=2;i<=n;i++)fac[i]=1ll*fac[i-1]*i%mod;
	finv[n]=ksm(fac[n],mod-2);
	for(i=n;i>=1;i--)finv[i-1]=1ll*finv[i]*i%mod;
	wl=1<<18;wn[0]=1;wn[1]=ksm(3,(mod-1)/wl);
	for(i=2;i<=wl;i++)wn[i]=1ll*wn[i-1]*wn[1]%mod;
}
int C(int x,int y)
{
	return 1ll*fac[x]*finv[y]%mod*finv[x-y]%mod;
}
void NTT(int a[],int len,int flg)
{
	for(int i=1;i>1;i>=1)for(int j=0;j>1]>>1)|(i&1?len>>1:0);
	NTT(A,len,1);NTT(B,len,1);
	for(i=0;i

 

 

 

 

省选模拟赛Round1Day2 旅游 宝石([CTS2019]珍珠) 线段([APIO2019]路灯)_第4张图片

 

题解:

分别考虑每一段1[l,r]的贡献(用set来维护连续段)

它可以使所有满足l<=a<=b<=r的[a,b]都加上它的存在时间(在它结束(分被裂或者合并)的时候统计)

把询问看作2维上的一个点

转为动态二维数点后CDQ分治+静态二维数点即可

代码:

#include
#include
#include
#include
using namespace std;
inline int gi()
{
	char c;int num=0,flg=1;
	while((c=getchar())<'0'||c>'9')if(c=='-')flg=-1;
	while(c>='0'&&c<='9'){num=num*10+c-48;c=getchar();}
	return num*flg;
}
#define N 300005
#define LL long long
set S;
set::iterator it1,it2;
struct node{
	int x,y,v,t,id;
	node(){}
	node(int a,int b,int c,int d,int e){x=a;y=b;v=c;t=d;id=e;}
	bool operator < (const node &T)const{
		return x>1,ql=l,qr=mid+1;
	for(int i=l;i<=r;i++){
		if(q[i].t<=mid){
			tmp[ql++]=q[i];
			if(q[i].v)update(q[i].y,q[i].v);
		}
		else{
			tmp[qr++]=q[i];
			if(!q[i].v)ans[q[i].id]+=query(q[i].y);
		}
	}
	for(int i=l;i<=r;i++)
		if(q[i].t<=mid&&q[i].v)update(q[i].y,-q[i].v);
	for(int i=l;i<=r;i++)q[i]=tmp[i];
	solve(l,mid);solve(mid+1,r);
}
int main()
{
	freopen("segment.in","r",stdin);
	freopen("segment.out","w",stdout);
	int i,x,l,r;
	n=gi();Q=gi();scanf("%s",ss+1);
	S.insert(0);S.insert(n+1);
	for(i=1;i<=n;i++){
		vis[i]=ss[i]-'0';
		if(!vis[i])S.insert(i);
	}
	for(i=1;i<=Q;i++){
		scanf("%s",op);
		if(op[0]=='t'){
			x=gi();it1=it2=S.lower_bound(x);
			if(vis[x]){
				it1--;
				cnt++,q[cnt]=node(*it1+1,*it2-1,i-las[*it1],cnt,0);
				if(*it1!=x-1)las[*it1]=i;
				if(*it2!=x+1)las[x]=i;
				S.insert(x);
			}
			else{
				it1--;it2++;
				if(*it1!=x-1)cnt++,q[cnt]=node(*it1+1,x-1,i-las[*it1],cnt,0);
				if(*it2!=x+1)cnt++,q[cnt]=node(x+1,*it2-1,i-las[x],cnt,0);
				S.erase(x);las[*it1]=i;
			}
			vis[x]^=1;
		}
		else{
			l=gi();r=gi()-1;
			cnt++,q[cnt]=node(l,r,0,cnt,++acnt);
			it1=S.lower_bound(l);
			if(*it1>r)ans[acnt]=i-las[*--it1];
		}
	}
	sort(q+1,q+cnt+1);
	solve(1,cnt);
	for(i=1;i<=acnt;i++)
		printf("%lld\n",ans[i]);
}

 

 

 

 

 

你可能感兴趣的:(总结)