C/C++教程

luogu P5492 [PKUWC2018]随机算法

本文主要是介绍luogu P5492 [PKUWC2018]随机算法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

题面传送门
考虑到这样做得到的图的性质,不难发现对于一个点,要么是最大独立集里面的点,要么周围有至少一个点在最大独立集内。
可以发现如果我们限定了当前最大独立集里面是什么点,那么其余的点都会被限定在一个固定的集合里面,且完全包含最大独立集,直接dp可以得到一个\(O(3^n)\)的做法,应该可以得到50pts。
但是实际上不用这样限定。我们设\(dp_{i,j}\)表示限定到了这个序列的第\(i\)位,当前最大独立集里面是\(j\)的方案数,那么接下来有两种操作:第一是放入一个在最大独立集里面的数,也就是不在\(j\)集合导出的图里面的点,另一种就是将\(j\)集合里面导出的图还没有安排的点选一个放进去,两种转移都是平凡的,时间复杂度\(O(n^22^n)\)。
虽然剪剪枝也能过,但是实际上似乎sosdp一下可以做到\(O(n2^n)\)?不过咱也不知道咱也不敢说。
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define ll long long
#define db double
#define lb long db
#define N (200000+5)
#define M ((1<<20)+5)
#define Ks (12+5)
#define mod 998244353
#define Mod (mod-1)
#define eps (1e-9)
#define ull unsigned ll
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
#define R(n) (rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using namespace std;
int n,m,q,z,x,y,op,Ls;ll Ans,A[N],B[N];
namespace Tree{
	#define ls now<<1
	#define rs now<<1|1
	int Fl[N<<2];ll F[N<<2],S[N<<2],S1[N<<2],S2[N<<2],Mx[N<<2];I void Up(int now){F[now]=F[ls]+F[rs];S[now]=S[ls]+S[rs];Mx[now]=max(Mx[ls],Mx[rs]);}
	I void BD(int l=1,int r=m+1,int now=1){S1[now]=r-l+1;S2[now]=1ll*(m-l+1+m-r+1)*(r-l+1)/2;if(l==r){S[now]=Mx[now]=(l^1?B[l]:0);F[now]=(l^1?B[l]:0)*(m-l+1);return;}int m=l+r>>1;BD(l,m,ls);BD(m+1,r,rs);Up(now);}
	I void PF(int now,int w){Fl[now]+=w;S[now]+=S1[now]*w;F[now]+=S2[now]*w;Mx[now]+=w;}I void P(int now){Fl[now]&&(PF(ls,Fl[now]),PF(rs,Fl[now]),Fl[now]=0);}
	I void Ins(int x,int y,int z,int l=1,int r=m+1,int now=1){if(x<=l&&r<=y) return PF(now,z);int m=l+r>>1;P(now);x<=m&&(Ins(x,y,z,l,m,ls),0);y>m&&(Ins(x,y,z,m+1,r,rs),0);Up(now);}
	I ll Qry(int x,int y,int z,int l=1,int r=m+1,int now=1){if(x>y) return 0;if(x<=l&&r<=y) return F[now]+S[now]*z;int m=l+r>>1;P(now);ll Fs=0;x<=m&&(Fs+=Qry(x,y,z,l,m,ls));y>m&&(Fs+=Qry(x,y,z,m+1,r,rs));return Fs;}
	I int Find(ll z,int l=1,int r=m+1,int now=1){if(l==r) return l-1;int m=l+r>>1;P(now);return z<=Mx[ls]?Find(z,l,m,ls):Find(z,m+1,r,rs);}
	#undef ls
	#undef rs
}
int main(){
	freopen("1.in","r",stdin);
	int i,j;scanf("%d%d%d",&n,&m,&q);for(i=1;i<=n;i++) scanf("%lld",&A[i]);for(i=1;i<=m;i++) scanf("%lld",&B[i]);B[m+1]=1e18;
	for(i=n;i;i--) A[i]-=A[i-1];for(i=m;i;i--) B[i]-=B[i-1]; Tree::BD();while(q--){
		scanf("%d%d%d",&op,&x,&y);if(op==1) {for(i=n-x+1;i<=n;i++) A[i]+=y;}else x^m?(Tree::Ins(m-x+1,m,y)):(B[1]+=y,Tree::Ins(2,m,y));
		z=2;Ans=(A[1]+B[1])*(n+m-1);
		for(i=2;i<=n;i++) Ls=Tree::Find(A[i]),Ans+=Tree::Qry(z,Ls,n-i+1)+A[i]*(n-i+m-Ls+1),z=Ls+1/*,cerr<<z<<' '<<Ans<<'\n'*/;printf("%lld\n",Ans+Tree::Qry(z,m,0));
	}
}
这篇关于luogu P5492 [PKUWC2018]随机算法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!