190913 CSP-S 2019模拟

A

l d x ldx ldx 级别的送分题
代码:

#include
#define ri register int
#define pb push_back
using namespace std;
const int rlen=1<<18|1;
typedef long long ll;
typedef long double ld;
inline char gc(){
	static char buf[rlen],*ib,*ob;
	(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
	return ib==ob?-1:*ib++;
}
inline int read(){
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
const int mod=1e9+7;
inline int add(int a,int b){return (a+=b)<mod?a:a-mod;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline void Add(int&a,int b){(a+=b)<mod?a:(a-=mod);}
inline void Dec(int&a,int b){(a-=b)<0?(a+=mod):a;}
inline void Mul(int&a,int b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,Mul(a,a))if(p&1)Mul(ret,a);return ret;}
const ld eps=1e-6;
inline int sgn(ld x){return (x>eps)-(x<eps);}
struct Node{
	ld vl;
	int a,b;
	friend inline bool operator<(Node a,Node b){
		int t=sgn(a.vl-b.vl);
		return t?t<0:a.b<b.b;
	}
};
priority_queue<Node>q;
int n,k;
vector<int>tg,fac,ifac;
vector<ld>ft;
inline void init(){
	tg.resize(n+1),fac.resize(n+1),ifac.resize(n+1),ft.resize(n+1);
	fac[0]=fac[1]=ifac[0]=ifac[1]=1;
	for(ri i=2;i<=n;++i)fac[i]=mul(fac[i-1],i),ifac[i]=mul(ifac[mod-mod/i*i],mod-mod/i);
	for(ri i=2;i<=n;++i)Mul(ifac[i],ifac[i-1]);
	for(ri i=1;i<=n;++i)ft[i]=ft[i-1]+log2(i);
}
inline ld ldxC(int n,int m){return ft[n]-ft[m]-ft[n-m];}
inline int C(int n,int m){return n<m?0:mul(fac[n],mul(ifac[m],ifac[n-m]));}
int main(){
	#ifdef ldxcaicai
	freopen("lx.in","r",stdin);
	#endif
	cin>>n>>k;
	init();
	for(ri i=0;i<=n;++i){
		tg[i]=i>>1;
		q.push((Node){ldxC(i,i>>1),i,1+(i&1)});
	}
	int res=0;
	while(k){
		Node x=q.top();
		q.pop();
		for(ri i=min(x.b,k);i;--i)Add(res,C(x.a,tg[x.a]));
		k-=min(x.b,k);
		--tg[x.a];
		if(tg[x.a]>=0)q.push((Node){ldxC(x.a,tg[x.a]),x.a,2});
	}
	cout<<res;
	return 0;
}

B

l d x ldx ldx 难度的回滚莫队+可回退化链表
代码:

#include
#define ri register int
#define pb push_back
using namespace std;
const int rlen=1<<18|1;
typedef long long ll;
inline char gc(){
	static char buf[rlen],*ib,*ob;
	(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
	return ib==ob?-1:*ib++;
}
inline int read(){
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
inline int Read(char*s){
	int tp=0;
	char ch=gc();
	while(!isalpha(ch))ch=gc();
	while(isalpha(ch))s[++tp]=ch,ch=gc();
	return tp;
}
const int N=1e5+5,M=3e5+5;
char s[M];
ll ans[N],ss,sum[M];
int pre[M],suf[M],cnt[M],tim[M];
int n,A,B,C,m,vl[M],g[M],L,Vl[N],ban[M],dep[M];
int son[M][26],pos[M],Len[N],treetot=1,tot=0;
inline void insert(char*s,int n,int vll){
	int p=1;
	for(ri x,i=1;i<=n;++i){
		x=s[i]-'a';
		if(!son[p][x])son[p][x]=++treetot,dep[son[p][x]]=dep[p]+1;
		p=son[p][x];
		pos[++tot]=p;
		vl[tot]=vll;
		sum[p]+=vll;
		++tim[p];
	}
}
int blo;
inline int findblo(int x){return (x-1)/blo+1;}
struct Qry{int l,r,id;friend inline bool operator<(Qry a,Qry b){return a.r>b.r;}};
vector<Qry>qry[1005];
inline ll dis(int a,int b){return (ll)(b-a-1)*(b-a)/2;}
inline void add(int p){
	bool ff=1;
	int t;
	if(tim[pos[p]]&&sum[pos[p]]>=ban[dep[pos[p]]])ff=0;
	sum[pos[p]]+=vl[p];
	++tim[pos[p]];
	if(sum[pos[p]]<ban[dep[pos[p]]])ff=0;
	if(ff){
		t=g[dep[pos[p]]];
		++cnt[t];
		if(cnt[t]==1){
			ss=ss+dis(pre[t],t)+dis(t,suf[t])-dis(pre[t],suf[t]);
			suf[pre[t]]=t,pre[suf[t]]=t;
		}
	}
}
inline void dec(int p){
	bool ff=1;
	int t;
	if(sum[pos[p]]<ban[dep[pos[p]]])ff=0;
	sum[pos[p]]-=vl[p];
	--tim[pos[p]];
	if(tim[pos[p]]&&sum[pos[p]]>=ban[dep[pos[p]]])ff=0;
	if(ff){
		t=g[dep[pos[p]]];
		--cnt[t];
		if(cnt[t]==0){
			ss=ss-dis(pre[t],t)-dis(t,suf[t])+dis(pre[t],suf[t]);
			suf[pre[t]]=suf[t],pre[suf[t]]=pre[t];
		}
	}
}
int ori=1;
inline void solvebig(int id){
	if(!qry[id].size())return;
	sort(qry[id].begin(),qry[id].end());
	int R=tot,L=(id-1)*blo+1;
	while(ori!=L)dec(ori++);
	for(ri i=0,up=qry[id].size();i<up;++i){
		while(R!=qry[id][i].r)dec(R--);
		while(L!=qry[id][i].l)dec(L++);
		ans[qry[id][i].id]=ss;
		while(L!=ori)add(--L);
	}
	while(R!=tot)add(++R);
}
inline ll gcd(ll a,ll b){ll t;while(b)t=a,a=b,b=t-t/a*a;return a;}
vector<int>tp;
int main(){
	#ifdef ldxcaicai
	freopen("lx.in","r",stdin);
	freopen("lx.out","w",stdout);
	#endif
	n=read(),A=read(),B=read(),C=read(),L=0;
	for(ri i=1;i<=n;++i)Vl[i]=read();
	for(ri len,i=1;i<=n;++i){
		len=Read(s);
		Len[i]=len+Len[i-1];
		L=max(L,len);
		insert(s,len,Vl[i]);
	}
	for(ri i=1;i<=L;++i)g[i]=read(),ban[i]=C>=(ll)A*i?(C-A*i+B-1)/B:0;
	blo=min(tot,300);
	for(ri i=2;i<=treetot;++i)if(sum[i]>=ban[dep[i]])tp.pb(g[dep[i]]);
	sort(tp.begin(),tp.end());
	for(ri i=0;i<tp.size();++i)++cnt[tp[i]];
	tp.erase(unique(tp.begin(),tp.end()),tp.end());
	if(tp.size()){
		pre[tp[0]]=0,suf[tp.back()]=L+1;
		suf[0]=tp[0],pre[L+1]=tp.back();	
		for(ri i=0;i<tp.size();++i){
			if(i)pre[tp[i]]=tp[i-1];
			if(i+1!=tp.size())suf[tp[i]]=tp[i+1];
		}
	}
	else pre[L+1]=0,suf[0]=L+1;
	ss=0;
	for(ri i=0;i!=L+1;i=suf[i])ss+=dis(i,suf[i]);
	m=read();
	for(ri i=1,l,r;i<=m;++i){
		l=Len[read()-1]+1,r=Len[read()];
		qry[findblo(l)].pb((Qry){l,r,i});
	}
	for(ri i=1,up=findblo(tot);i<=up;++i)solvebig(i);
	ll all=(ll)L*(L+1)/2,g;
	for(ri i=1;i<=m;++i){
		g=gcd(all,ans[i]);
		cout<<(all-ans[i])/g<<'/'<<all/g<<'\n';
	}
	return 0;
}

C

z x y zxy zxy 难度的算计建图+ l d x ldx ldx 难度的 01 t r i e 01trie 01trie 合并优化 S G SG SG 图上 d p dp dp
由于前者是 z x y zxy zxy 难度于是放弃了,后者是这个题
COT3的代码:

#include
#define ri register int
#define pb push_back
using namespace std;
const int rlen=1<<18|1;
char buf[rlen],*ib=buf,*ob=buf;
#define gc() (((ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin)),ib==ob)?-1:*ib++)
inline int read(){
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
const int N=1e5+5,Dep=15,M=3e6+5;
int n,col[N],rt[N],f[N];
vector<int>e[N],ans;
namespace trie{
	#define lc (son[p][0])
	#define rc (son[p][1])
	int son[M][2],tg[M],tot=0;
	bool ok[M];
	inline void pushnow(int p,int v,int dep){
		if(v>>dep&1)swap(lc,rc);
		tg[p]^=v;
	}
	inline void pushdown(int p,int dep){if(dep&&tg[p])pushnow(lc,tg[p],dep-1),pushnow(rc,tg[p],dep-1);tg[p]=0;}
	inline void update(int&p,int v,int dep=Dep){
		p=++tot;
		if(dep==-1){ok[p]=1;return;}
		update(son[p][v>>dep&1],v,dep-1);
	}
	inline int merge(int a,int b,int dep=Dep){
		if(!a||!b)return a|b;
		if(dep==-1)return ok[a]|=ok[b],a;
		pushdown(a,dep),pushdown(b,dep);
		son[a][0]=merge(son[a][0],son[b][0],dep-1);
		son[a][1]=merge(son[a][1],son[b][1],dep-1);
		return ok[a]=ok[son[a][0]]&ok[son[a][1]],a;
	}
	inline int mex(int p,int dep=Dep){
		if(!p||dep==-1)return 0;
		pushdown(p,dep);
		if(!ok[lc])return mex(lc,dep-1);
		return (1<<dep)|mex(rc,dep-1);
	}
	#undef lc
	#undef rc
}
void dfs1(int p,int ft){
	int s=0;
	for(ri i=0,v;i<e[p].size();++i){
		if((v=e[p][i])==ft)continue;
		dfs1(v,p);
		s^=f[v];
	}
	if(!col[p])trie::update(rt[p],s);
	for(ri i=0,v;i<e[p].size();++i){
		if((v=e[p][i])==ft)continue;
		trie::pushnow(rt[v],s^f[v],Dep);
		rt[p]=trie::merge(rt[p],rt[v]);
	}
	f[p]=trie::mex(rt[p]);
}
void dfs2(int p,int ft,int pre){
	for(ri i=0,v;i<e[p].size();++i){
		if((v=e[p][i])==ft)continue;
		pre^=f[v];
	}
	if(!col[p]&&!pre)ans.pb(p);
	for(ri i=0,v;i<e[p].size();++i){
		if((v=e[p][i])==ft)continue;
		dfs2(v,p,pre^f[v]);
	}
}
int main(){
	#ifdef ldxcaicai
	freopen("lx.in","r",stdin);
	#endif
	n=read();
	for(ri i=1;i<=n;++i)col[i]=read();
	for(ri i=1,u,v;i<n;++i){
		u=read(),v=read();
		e[u].pb(v);
		e[v].pb(u);
	}
	dfs1(1,0);
	dfs2(1,0,0);
	if(!ans.size())puts("-1");
	else{
		sort(ans.begin(),ans.end());
		for(ri i=0;i<ans.size();++i)cout<<ans[i]<<' ';
	}
	return 0;
}

你可能感兴趣的:(#,题解)