省选联测29
衡石 6
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
?