省选模拟4.3
A. Max
设 \(f_{i,sta,j}\) 表示考虑前 \(i\) 个数,做的操作状态为 \(sta\) 最大值为 \(j\) 的概率
\(g_{i,sta,j}\) 为第 \(i\) 个数,做的操作状态为 \(sta\) 加起来的值是 \(j\) 时的概率
转移时枚举一个没有选过的集合
Code
#include<bits/stdc++.h>
#define int long long//MEM LIM OVER FLOW
#define meow(args...) fprintf(stderr,args)
#define inf 0x3f3f3f3f3f3f3f3f
#define mod 1000000007
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int n,m,c,U,V,ans,p;
int a[50][15][5],f[50][1024][40],g[50][1024][40];
signed main(){
#ifdef LOCAL
freopen("in","r",stdin);
freopen("out","w",stdout);
#endif
freopen("max.in","r",stdin);
freopen("max.out","w",stdout);
n=read(),m=read(),c=read();U=(1<<m)-1,V=m*c;
for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) for(int k=0;k<=c;k++) a[j][i][k]=read();
for(int i=1;i<=n;i++){
g[i][0][0]=1;
for(int j=1;j<=m;j++) for(int k=0;k<=c;k++){
for(int sta=0;sta<=U;sta++) if(((sta>>(j-1))&1)==0) for(int v=0;v<=V;v++) if(g[i][sta][v]){
(g[i][sta|(1<<(j-1))][v+k]+=g[i][sta][v]*a[i][j][k])%=mod;
}
}
}
f[0][0][0]=1;
for(int i=1;i<=n;i++) for(int sta=0,vs;sta<=U;sta++) for(int v=0;v<=V;v++) if(f[i-1][sta][v]){
vs=sta^U;
(f[i][sta][v]+=f[i-1][sta][v])%=mod;
for(int vsta=vs;vsta;vsta=(vsta-1)&vs) for(int vv=0;vv<=V;vv++) if(g[i][vsta][vv]){
(f[i][sta|vsta][max(v,vv)]+=f[i-1][sta][v]*g[i][vsta][vv])%=mod;
}
}
for(int i=0;i<=V;i++) (ans+=i*f[n][U][i])%=mod;
printf("%lld\n",ans);
return 0;
}
B. Paint
发现答案必然经过 \(x=\frac{w}{2}\) 或 \(y=\frac{h}{2}\)
考虑一个答案的下界 \(2*(\max(h,w)+1)\) 就是只保留竖着或者横着的一条
答案的矩形的长宽分别为 \(a,b\) 的话,假设 \(a<b\)
那么 \(b\) 一定要大于 \(\frac{h}{2}\) 才有可能成为答案,此时必定经过 \(y=\frac{h}{2}\)
\(a>b\) 时同理
于是考虑扫描线维护,枚举上边界对每一个下边界维护有个左右边界
用单调栈维护即可,在更新时在线段树区间对应修改
枚举右边界的同理
Code
#include<bits/stdc++.h>
#define int long long//MEM LIM OVER FLOW
#define meow(args...) fprintf(stderr,args)
#define lson rt<<1
#define rson rt<<1|1
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int n,w,h,ans;
int Ox[400010],Oy[400010],totx,toty;
int stkl[400010],stkr[400010],pl,pr;
struct node{int x,y;}L[400010];
struct seg{int mx,atag;}st[400010*4];
vector<int>vec[400010];
inline void pushup(int rt){st[rt].mx=max(st[lson].mx,st[rson].mx);}
inline void pushdown(int rt){
if(st[rt].atag){
st[lson].atag+=st[rt].atag;st[lson].mx+=st[rt].atag;
st[rson].atag+=st[rt].atag;st[rson].mx+=st[rt].atag;
st[rt].atag=0;
}
}
void buildx(int rt,int l,int r){
st[rt].atag=0;
if(l==r) return st[rt].mx=h-Ox[l],void();
int mid=(l+r)>>1;
buildx(lson,l,mid);
buildx(rson,mid+1,r);
pushup(rt);
}
void buildy(int rt,int l,int r){
st[rt].atag=0;
if(l==r) return st[rt].mx=w-Oy[l],void();
int mid=(l+r)>>1;
buildy(lson,l,mid);
buildy(rson,mid+1,r);
pushup(rt);
}
void upd(int rt,int l,int r,int L,int R,int k){
if(L>R||R==0) return;
if(L<=l&&r<=R) return st[rt].atag+=k,st[rt].mx+=k,void();
int mid=(l+r)>>1;pushdown(rt);
if(L<=mid) upd(lson,l,mid,L,R,k);
if(R>mid) upd(rson,mid+1,r,L,R,k);
pushup(rt);
}
int query(int rt,int l,int r,int L,int R){
if(L<=l&&r<=R) return st[rt].mx;
int mid=(l+r)>>1,res=0;pushdown(rt);
if(L<=mid) res=max(res,query(lson,l,mid,L,R));
if(R>mid) res=max(res,query(rson,mid+1,r,L,R));
return res;
}
void print(int rt,int l,int r){
printf("l : %lld r : %lld mx : %lld\n",l,r,st[rt].mx);
if(l==r) return ;
int mid=(l+r)>>1;pushdown(rt);
print(lson,l,mid);
print(rson,mid+1,r);
}
signed main(){
#ifdef LOCAL
freopen("in","r",stdin);
freopen("out","w",stdout);
#endif
freopen("paint.in","r",stdin);
freopen("paint.out","w",stdout);
w=read(),h=read(),n=read();
for(int i=1;i<=n;i++) Ox[i]=L[i].x=read(),Oy[i]=L[i].y=read();
Ox[n+1]=0,Ox[n+2]=w,Oy[n+1]=0,Oy[n+2]=h;
sort(Ox+1,Ox+1+n+2);sort(Oy+1,Oy+1+n+2);
totx=unique(Ox+1,Ox+1+n+2)-Ox-1;
toty=unique(Oy+1,Oy+1+n+2)-Oy-1;
for(int i=1;i<=n;i++){
L[i].x=lower_bound(Ox+1,Ox+1+totx,L[i].x)-Ox;
L[i].y=lower_bound(Oy+1,Oy+1+toty,L[i].y)-Oy;
}
for(int i=1;i<=n;i++) vec[L[i].y].emplace_back(i);
buildy(1,1,toty);
for(int i=1;i<=toty;i++){
if(i>1) ans=max(ans,2*(Oy[i]+query(1,1,toty,1,i-1)));
for(auto x:vec[i]){
if(Ox[L[x].x]<=w/2){
while(pl&&L[stkl[pl]].x<=L[x].x){upd(1,1,toty,L[stkl[pl-1]].y,L[stkl[pl]].y-1,Ox[L[stkl[pl]].x]);pl--;}
if(!pl||L[x].y!=L[stkl[pl]].y){stkl[++pl]=x;upd(1,1,toty,L[stkl[pl-1]].y,L[stkl[pl]].y-1,-Ox[L[stkl[pl]].x]);}
}
if(Ox[L[x].x]> w/2){
while(pr&&L[stkr[pr]].x>=L[x].x){upd(1,1,toty,L[stkr[pr-1]].y,L[stkr[pr]].y-1,w-Ox[L[stkr[pr]].x]);pr--;}
if(!pr||L[x].y!=L[stkr[pr]].y){stkr[++pr]=x;upd(1,1,toty,L[stkr[pr-1]].y,L[stkr[pr]].y-1,-w+Ox[L[stkr[pr]].x]);}
}
}
}
for(int i=1;i<=totx;i++) vec[i].clear();pl=pr=0;
for(int i=1;i<=n;i++) vec[L[i].x].emplace_back(i);
buildx(1,1,totx);
for(int i=1;i<=totx;i++){
if(i>1) ans=max(ans,2*(Ox[i]+query(1,1,totx,1,i-1)));
for(auto x:vec[i]){
if(Oy[L[x].y]<=h/2){
while(pl&&L[stkl[pl]].y<=L[x].y){upd(1,1,totx,L[stkl[pl-1]].x,L[stkl[pl]].x-1,Oy[L[stkl[pl]].y]);pl--;}
if(L[x].x!=L[stkl[pl]].x){stkl[++pl]=x;upd(1,1,totx,L[stkl[pl-1]].x,L[stkl[pl]].x-1,-Oy[L[stkl[pl]].y]);}
}
if(Oy[L[x].y]> h/2){
while(pr&&L[stkr[pr]].y>=L[x].y){upd(1,1,totx,L[stkr[pr-1]].x,L[stkr[pr]].x-1,h-Oy[L[stkr[pr]].y]);pr--;}
if(L[x].x!=L[stkr[pr]].x){stkr[++pr]=x;upd(1,1,totx,L[stkr[pr-1]].x,L[stkr[pr]].x-1,-h+Oy[L[stkr[pr]].y]);}
}
}
}
printf("%lld\n",ans);
return 0;
}
C. Decompose
设 \(f_{i,j}\) 表示当 \(i\) 时链上第 \(j\) 个时子树内的最大值
转移可以写成 \(\text{max-add}\) 矩阵的形式,不合法的地方赋 \(-inf\)
然后只要用数据结构维护这个 \(ddp\) 就行了
用树剖维护,分别维护轻重儿子的信息转移就行
Code
#include<bits/stdc++.h>
#define int long long//MEM LIM OVER FLOW
#define meow(args...) fprintf(stderr,args)
#define lson rt<<1
#define rson rt<<1|1
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int n,m,L;
int sumc[100010],w[100010][5];
int dfn[100010],top[100010],bot[100010],fa[100010],dep[100010],siz[100010],son[100010],id[100010],clo;
vector<int>g[100010];
multiset<int>maxc[100010][5];
struct mat{
int a[5][5];
inline void init(){for(int i=1;i<=L;i++) for(int j=1;j<=L;j++) a[i][j]=-inf;}
inline mat operator*(const mat &b)const{
mat c;c.init();
for(int i=1;i<=L;i++) for(int k=1;k<=L;k++) for(int j=1;j<=L;j++) c.a[i][j]=max(c.a[i][j],a[i][k]+b.a[k][j]);
return c;
}
}f[100010],t[100010],tmp;
struct seg{mat f;}st[100010*4];
inline void pushup(int rt){st[rt].f=st[rson].f*st[lson].f;}
void upd(int rt,int l,int r,int pos){
if(l==r) return st[rt].f=f[id[l]],void();
int mid=(l+r)>>1;
if(pos<=mid) upd(lson,l,mid,pos);
else upd(rson,mid+1,r,pos);
pushup(rt);
}
mat query(int rt,int l,int r,int L,int R){
if(L<=l&&r<=R) return st[rt].f;
int mid=(l+r)>>1;
if(R<=mid) return query(lson,l,mid,L,R);
if(L>mid) return query(rson,mid+1,r,L,R);
return query(rson,mid+1,r,L,R)*query(lson,l,mid,L,R);
}
inline void build(int x){
if(g[x].size()==0){f[x].init();f[x].a[1][1]=w[x][1];}
if(son[x]){
for(int i=1;i<=L;i++) f[x].a[i][1]=sumc[x]+w[x][1];
for(int i=2;i<=L;i++) for(int j=1;j<=L;j++){
f[x].a[j][i]=sumc[x]+w[x][i]+*maxc[x][i-1].rbegin();
if(i==j+1) f[x].a[j][i]=sumc[x]+w[x][i];
}
}
}
void dfs1(int x,int fa,int dep){
::fa[x]=fa,::dep[x]=dep,siz[x]=1;
int maxson=-1;
for(auto y:g[x]){
dfs1(y,x,dep+1);siz[x]+=siz[y];
if(siz[y]>maxson) maxson=siz[y],son[x]=y;
}
}
void dfs2(int x,int topf){
dfn[x]=++clo;top[x]=topf;bot[topf]=x;id[clo]=x;
if(!son[x]) return;
dfs2(son[x],topf);
for(auto y:g[x]) if(y!=son[x]) dfs2(y,y);
}
void dfs3(int x){
for(auto y:g[x]) dfs3(y);
build(x);upd(1,1,n,dfn[x]);
if(top[x]==x){
int mx=-inf;
t[x]=query(1,1,n,dfn[top[x]],dfn[bot[x]]);
for(int i=1;i<=L;i++) mx=max(mx,t[x].a[1][i]);sumc[fa[x]]+=mx;
for(int i=1;i<=L;i++) maxc[fa[x]][i].insert(t[x].a[1][i]-mx);
}
}
inline void Tupd(int x){
int lst=x;
while(top[x]!=1){
tmp=query(1,1,n,dfn[top[x]],dfn[bot[top[x]]]);
int mx=-inf;
for(int i=1;i<=L;i++) mx=max(mx,tmp.a[1][i]);sumc[fa[top[x]]]-=mx;
for(int i=1;i<=L;i++) maxc[fa[top[x]]][i].erase(maxc[fa[top[x]]][i].find(tmp.a[1][i]-mx));
x=fa[top[x]];
}
x=lst;
while(top[x]!=1){
int mx=-inf;
build(x);upd(1,1,n,dfn[x]);
tmp=query(1,1,n,dfn[top[x]],dfn[bot[top[x]]]);
for(int i=1;i<=L;i++) mx=max(mx,tmp.a[1][i]);sumc[fa[top[x]]]+=mx;
for(int i=1;i<=L;i++) maxc[fa[top[x]]][i].insert(tmp.a[1][i]-mx);
x=fa[top[x]];
}
build(x);upd(1,1,n,dfn[x]);
}
signed main(){
#ifdef LOCAL,
freopen("in","r",stdin);
freopen("out","w",stdout);
#endif
freopen("decompose.in","r",stdin);
freopen("decompose.out","w",stdout);
n=read(),m=read(),L=read();
for(int i=2;i<=n;i++) g[read()].emplace_back(i);
for(int i=1;i<=n;i++) for(int j=1;j<=L;j++) w[i][j]=read();
for(int i=1;i<=n;i++) for(int j=1;j<=L;j++) maxc[i][j].insert(-inf);
dfs1(1,0,1),dfs2(1,1);dfs3(1);
for(int i=1,x,mx;i<=m;i++){
x=read();for(int j=1;j<=L;j++) w[x][j]=read();Tupd(x);
tmp=query(1,1,n,dfn[1],dfn[bot[1]]);mx=-inf;
for(int i=1;i<=L;i++) mx=max(mx,tmp.a[1][i]);
printf("%lld\n",mx);
}
return 0;
}