省选联测29

衡石 6
image

A.Alice和Bob双在玩游戏(gametwice)

是一个非公平组合游戏,所以跟SG值没啥关系,考虑别的做法。
发现操作时可以贪心的选一个点,使得双方最优策略下,自己比对方可操作的次数尽量多,恰好是个dag于是可以直接dp求,注意dp值最劣是\(0\),然后就是简单背包了。

点击查看代码
// ubsan: undefined
// accoders
#include <bits/stdc++.h>
typedef long long ll;typedef unsigned long long ull; typedef double db;typedef long double ldb;
#define fre(x) freopen(#x ".in","r",stdin),freopen(#x ".out","w",stdout)
#define Rep(i,a,b) for(int i=a;i<=b;++i) 
#define Dwn(i,a,b) for(int i=a;i>=b;--i)
#define pii pair<int,int>
#define mair make_pair
#define fir first
#define sec second
using namespace std;

const int maxn=5e2+10,B=130000,Mod=998244353;
const int INF=0x80808080;

struct Arr{
	int f[130010*2];
	int &operator [](const int &i){ return f[i+B]; }
	int operator [](const int &i)const{ return f[i+B]; }
}f;

int n,m;char col[maxn];
int g[maxn];

vector<int>E[maxn],G[maxn];
int deg[maxn];

void Dp(){
	queue<int>q;memset(g,0x80,sizeof(g));
	Rep(i,1,n)if(!deg[i])q.push(i),g[i]=0;
	while(!q.empty()){
		int u=q.front();q.pop();
		if(g[u]==INF){
			if(col[u]=='B'){ g[u]=0; for(auto v : E[u])g[u]=min(g[u],g[v]-1);}
			else { g[u]=0;for(auto v : E[u])g[u]=max(g[u],g[v]+1); }
		}
		for(auto v : G[u])!(--deg[v]) && (q.push(v),0);
	}
}

void Sol(){
	f[0]=1;
	Rep(i,1,n){
		if(g[i]>=0){ Dwn(j,130000,-130000)if(f[j])f[j+g[i]]=(f[j+g[i]]+f[j])%Mod; }
		else Rep(j,-130000,130000)if(f[j])f[j+g[i]]=(f[j+g[i]]+f[j])%Mod;
	}
	int ans=0;
	Rep(i,1,130000)ans=(ans+f[i])%Mod;
	cout<<ans<<"\n";
}

void solve(){
	cin>>n>>m>>(col+1);
	Rep(i,1,m){ int u,v;cin>>u>>v;E[u].emplace_back(v);G[v].emplace_back(u);++deg[u]; }
	Dp();Sol();
}

int main (){ fre(gametwice);ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);return solve(),0; }

B.时代的眼泪super plus

肯定是个根号做法,考虑分块,对于每个整块的信息,发现整体跳的时候,会出现某个点在另一个点的子树内,此时深度更大的这个点一定不优,可以直接删了打lazy。剩下的每次暴力跳,并在树上打vis,遇到访问过的点,说明它可以被删了,这样每个点只会被访问1次,于是复杂度是 \(O(n \sqrt n)\)的。对于散块的修改,目前能过的做法是直接把lazy下放然后重构,查询也差不多,需要求k级祖先,由于极度卡常所以书剖好像更优秀?常数瓶颈是内存访问,尽量避免封装使内存访问连续,倍增长剖等内存用量大,可能常数也过不去。

点击查看代码
// ubsan: undefined
// accoders
#include <bits/stdc++.h>
typedef long long ll;typedef unsigned long long ull; typedef double db;typedef long double ldb;
#define fre(x) freopen(#x ".in","r",stdin),freopen(#x ".out","w",stdout)
#define Rep(i,a,b) for(int i=a;i<=b;++i) 
#define Dwn(i,a,b) for(int i=a;i>=b;--i)
#define bint bitset<maxn>
#define pii pair<int,int>
#define mair make_pair
#define fir first
#define sec second
using namespace std;

const int maxn=2e5+10;
char buf[1<<20],*p1,*p2;
char gc(){return p1==p2&&(p2=(p1=buf)+fread(p1=buf,1,1<<20,stdin),p1==p2)?EOF:*p1++;}
int read(){
	int x=0;bool f=0;char c=gc();
	while(!isdigit(c)){if(c=='-')f=1;c=gc();}
	while(isdigit(c))x=x*10+(c^48),c=gc();
	return f ? -x : x;
}

int n,m,Root;
int a[maxn];
bint vis[580];
bool Sflag=true;

struct Graph{
	struct eg{ int from,to,next,dis; }e[maxn*2];
	int len,head[maxn];
	void lqx(int from,int to,int dis)
	{ e[++len].from=from,e[len].to=to,e[len].next=head[from],head[from]=len;e[len].dis=dis; }
	int fa[maxn],dep[maxn];ll dis[maxn];
	int top[maxn],son[maxn],siz[maxn],Te,dfn[maxn],rk[maxn];
	void Dfs(int u){
		siz[u]=1;
		for(int i=head[u];i;i=e[i].next){
			int v=e[i].to;if(v==fa[u])continue;
			fa[v]=u,dep[v]=dep[u]+1,dis[v]=dis[u]+e[i].dis;
			Dfs(v);siz[u]+=siz[v];
			if(!son[u] || siz[v]>siz[son[u]])son[u]=v;
		}
	}
	void Dfs2(int u,int tp){
		top[u]=tp;dfn[u]=++Te;rk[Te]=u;
		if(son[u])Dfs2(son[u],tp);
		for(int i=head[u];i;i=e[i].next){
			int v=e[i].to;if(v==fa[u] || v==son[u])continue;
			Dfs2(v,v);
		}
	}
	int Fa(int u,int k){
		if(k>=dep[u] || u==Root)return Root;
		while(k){
			int len=min(k,dep[u]-dep[top[u]]);
			u=rk[dfn[u]-len];k-=len;
			if(!k)break;
			--k;u=fa[u];
		}
		return u;
	}
}G;

struct Seg{
	struct Tree{ int val,lazy; }tr[maxn<<2];
	void Pushup(int rt){ tr[rt].val=min(tr[rt<<1].val,tr[rt<<1|1].val); }
	void Update(int rt,int w){ tr[rt].val+=w,tr[rt].lazy+=w; }
	void Pushdown(int rt){ if(tr[rt].lazy)Update(rt<<1,tr[rt].lazy),Update(rt<<1|1,tr[rt].lazy),tr[rt].lazy=0; }
	void Build(int rt,int l,int r){
		if(l==r)return tr[rt].val=G.dep[a[l]],void();
		int mid=(l+r)>>1;Build(rt<<1,l,mid),Build(rt<<1|1,mid+1,r);
		Pushup(rt);
	}
	void Modify(int rt,int l,int r,int s,int t,int w){
		if(s<=l && t>=r)return Update(rt,w);
		int mid=(l+r)>>1;Pushdown(rt);
		if(s<=mid)Modify(rt<<1,l,mid,s,t,w);
		if(t>mid)Modify(rt<<1|1,mid+1,r,s,t,w);
		Pushup(rt);
	}
	int Query(int rt,int l,int r,int s,int t){
		if(s<=l && t>=r)return tr[rt].val;
		int mid=(l+r)>>1,res=maxn;Pushdown(rt);
		if(s<=mid)res=Query(rt<<1,l,mid,s,t);
		if(t>mid)res=min(res,Query(rt<<1|1,mid+1,r,s,t));
		return res;
	}
}T;

int cnt[maxn];
int tmp[maxn];

struct Block{
	vector<int>vec;
	int L,R,id;ll Ans;int lazy;
	void ReBuild(){
		Ans=LLONG_MAX;vec.resize(R-L+1);
		Rep(i,L,R)Ans=min(Ans,G.dis[a[i]]),vec[i-L]=a[i];
	}
	void Release(){ if(!lazy)return; Rep(i,L,R)a[i]=G.Fa(a[i],lazy); lazy=0; }
	void Modify(int l,int r){ Release();Rep(i,l,r)a[i]=G.fa[a[i]];ReBuild(); }
	void Addall(){
		++lazy;if(!Ans)return;
		int len=0,u;
		for(auto it : vec){
			u=G.fa[it];Ans=min(Ans,G.dis[u]);
			if(vis[id][u])continue;
			vis[id][u]=true;tmp[++len]=u;
		}
		vec.assign(tmp+1,tmp+len+1);
	}
	ll Query(int l,int r){
		Release();ll res=LLONG_MAX;
		Rep(i,l,r)res=min(res,G.dis[a[i]]);
		ReBuild();
		return res;
	}
}B[580];

int siz,blen,bel[maxn];
int cc[3]={0,0,0};

void Init(){
	siz=sqrt(n*0.6);
	blen=ceil(1.0*n/siz);
	Rep(i,1,blen){ B[i].L=B[i-1].R+1,B[i].R=min(n,i*siz);B[i].id=i;B[i].ReBuild(); Rep(j,B[i].L,B[i].R)bel[j]=i; }
}

void Sol(int l,int r){
	int bl=bel[l],br=bel[r];
	if(bl==br)return B[bl].Modify(l,r);
	Rep(i,bl+1,br-1)B[i].Addall();
	B[bl].Modify(l,B[bl].R),B[br].Modify(B[br].L,r);
}

ll Ask(int l,int r){
	int bl=bel[l],br=bel[r];
	if(bl==br)return B[bl].Query(l,r);
	ll res=LLONG_MAX;
	Rep(i,bl+1,br-1)res && (res=min(res,B[i].Ans));
	res && (res=min(res,B[bl].Query(l,B[bl].R)));
	res && (res=min(res,B[br].Query(B[br].L,r)));
	return res;
}

double Time(){ return 1.0*clock()/CLOCKS_PER_SEC; }

void Work1(){
	T.Build(1,1,n);
	while (m--) {
        int opt, l, r;
		opt=read(),l=read(),r=read();
        if (opt == 1)
            T.Modify(1, 1, n, l, r, -1);
        else
			printf("%d\n",max(0,T.Query(1,1,n,l,r)));
	}
}

struct QQ{ int opt,l,r; }Q[maxn];

void solve(){
	n=read(),m=read(),Root=read();Rep(i,2,n){ int u,v,w;u=read(),v=read(),w=read();G.lqx(u,v,w),G.lqx(v,u,w);Sflag&=(w==1); }
	ll sum=0;G.Dfs(Root);Rep(i,1,n)a[i]=read(),sum+=G.dep[a[i]];
	if(Sflag)return Work1();
	Init();G.Dfs2(Root,Root);G.fa[Root]=Root;
	Rep(i,1,m){
		int opt,l,r;
		opt=read(),l=read(),r=read();
		if(opt==1)Sol(l,r);
		else printf("%lld\n",Ask(l,r));
	}
}

int main (){ 
	fre(tearssp);
	return solve(),0; 
}

C.钩子Plus

posted @ 2023-02-10 16:18  Delov  阅读(43)  评论(2编辑  收藏  举报