【2020省选模拟】题解

T1

考虑转成切比雪夫距离后记录四个边界 d p dp dp
每次暴力枚举下一个作为新边界的点 d p dp dp,剩下加入点直接计算和新矩形的答案
由于显然不可能左右横跳着选,这样能把所有情况考虑进去

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define y1 shinkle
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ib==ob)?EOF:*ib++;
}
inline int read(){
    char ch=gc();
    int res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline ll readll(){
    char ch=gc();
    ll res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline int readstring(char *s){
	int top=0;char ch=gc();
	while(isspace(ch))ch=gc();
	while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
	s[top+1]='\0';return top;
}
template<typename tp>inline void chemx(tp &a,tp b){a=max(a,b);}
template<typename tp>inline void chemn(tp &a,tp b){a=min(a,b);}
cs int M=23;
int f[M][M][M][M];
int n,m,id[M][M],cnt,vs[90];
int x[90],y[90];
char s[M][M];
inline int calc(int lx,int rx,int ly,int ry,int i){
	//cout<<i<<" "<<x[i]<<" "<<lx<<'\n';
	return max(max(x[i]-lx,rx-x[i]),max(y[i]-ly,ry-y[i]));
}
int main(){
	#ifdef Stargazer
	freopen("lx.in","r",stdin);
	#endif
	n=read(),m=read();
	memset(f,127/2,sizeof(f));int ans=f[0][0][0][0],INF=f[0][0][0][0];
	for(int i=1;i<=n;i++){
		readstring(s[i]);
		for(int j=1;j<=m;j++)if(s[i][j]=='#'){
			cnt++;
			x[cnt]=i+j,y[cnt]=m+i-j+1;
			f[x[cnt]][x[cnt]][y[cnt]][y[cnt]]=0;
		//	cout<<i+j<<" "<<m+i-j+1<<" "<<cnt<<'\n';
		}
	}
	for(int lx=22;lx;lx--)
	for(int rx=lx;rx<=22;rx++)
	for(int ly=22;ly;ly--)
	for(int ry=ly;ry<=22;ry++)if(f[lx][rx][ly][ry]<INF){
		bool rest=0;int pv=f[lx][rx][ly][ry];
		//cout<<lx<<" "<<rx<<" "<<ly<<" "<<ry<<" "<<pv<<'\n';
		for(int i=1;i<=cnt;i++)vs[i]=(lx<=x[i]&&x[i]<=rx&&ly<=y[i]&&y[i]<=ry);
		for(int i=1;i<=cnt;i++)if(!vs[i]){
			rest=1;
			int vl=calc(lx,rx,ly,ry,i),
			plx=min(lx,x[i]),prx=max(rx,x[i]),ply=min(ly,y[i]),pry=max(ry,y[i]);
		//	cout<<i<<" "<<vl<<'\n';
			for(int j=1;j<=cnt;j++)if(!vs[j]&&j!=i&&(plx<=x[j]&&x[j]<=prx&&ply<=y[j]&&y[j]<=pry)){
				vl+=calc(plx,prx,ply,pry,j);
				//cout<<j<<" "<<vl<<'\n';
			}chemn(f[plx][prx][ply][pry],pv+vl);
		}
		if(!rest)chemn(ans,f[lx][rx][ly][ry]);
	}cout<<ans<<'\n';
}

T2

考虑显然可以列出状态
如果没有环可以直接 d p dp dp
现在有环可以先强制平局然后利用 s p f a spfa spfa迭代

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define y1 shinkle
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ib==ob)?EOF:*ib++;
}
inline int read(){
    char ch=gc();
    int res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline ll readll(){
    char ch=gc();
    ll res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline int readstring(char *s){
	int top=0;char ch=gc();
	while(isspace(ch))ch=gc();
	while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
	s[top+1]='\0';return top;
}
template<typename tp>inline void chemx(tp &a,tp b){a=max(a,b);}
template<typename tp>inline void chemn(tp &a,tp b){a=min(a,b);}
cs int N=100005,M=200005;
struct node{
	int x,y,pre,now;
};
queue<node> q;
vector<int> e[N];
int f[N][6],cnt[N][6][3];
int fak[6],bel[6],kd[6];
inline void insert(int x,int y,int now){
	int pre=f[x][y];
	if(pre==now)return;
	q.push(node{x,y,pre,now});
	f[x][y]=now;
}
inline void push(int x,int y){
	int k;
	if(kd[y]){
		if(cnt[x][y][0])k=0;
		else if(cnt[x][y][1])k=1;
		else k=2;
	}
	else{
		if(cnt[x][y][2])k=2;
		else if(cnt[x][y][1])k=1;
		else k=0;
	}insert(x,y,k);
}
int d[N],n,m;
char str[10];
int main(){
	#ifdef Stargazer
	freopen("lx.in","r",stdin);
	freopen("my.out","w",stdout);
	#endif
	n=read(),m=read();
	for(int i=1;i<=m;i++){
		int u=read(),v=read();
		d[u]++,e[v].pb(u);
	}
	readstring(str);
	for(int i=0;i<6;i++)bel[i]=(str[i+1]=='A');
	readstring(str);
	for(int i=0;i<6;i++)fak[i]=(str[i+1]=='1'),kd[i]=fak[i]^bel[i];
	for(int i=1;i<=n;i++)
	for(int j=0;j<6;j++){
		f[i][j]=1;
		cnt[i][j][1]=d[i];
	}
	for(int i=1;i<=n;i++)if(!d[i])for(int j=0;j<6;j++){
		if(bel[j])insert(i,j,2);
		else insert(i,j,0);
	}
	while(q.size()){
		node t=q.front();q.pop();
		int x=t.x,y=t.y,pre=t.pre,now=t.now;
	//	cout<<x<<" "<<y<<'\n';
		y=(y+5)%6;
		for(int v:e[x]){
			cnt[v][y][pre]--,cnt[v][y][now]++;
			push(v,y);
		}
	}
	for(int i=1;i<=n;i++){
		switch(f[i][0]){
			case 0:putchar('A');break;
			case 1:putchar('D');break;
			case 2:putchar('B');break;
		}
	}return 0;
}

T3

考虑分析一下,只和每个点有多少个出 / 入, = = = / ≠ x \not=x =x有关
只考虑 = x =x =x怎么求,点分治后移一下项使得互相无关,然后用哈希表记一下可以 O ( n l o g n ) O(nlogn) O(nlogn)

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define y1 shinkle
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ib==ob)?EOF:*ib++;
}
inline int read(){
    char ch=gc();
    int res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline ll readll(){
    char ch=gc();
    ll res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline int readstring(char *s){
	int top=0;char ch=gc();
	while(isspace(ch))ch=gc();
	while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
	s[top+1]='\0';return top;
}
template<typename tp>inline void chemx(tp &a,tp b){a=max(a,b);}
template<typename tp>inline void chemn(tp &a,tp b){a=min(a,b);}
int mod;
inline int add(int a,int b){return (a+b)>=mod?(a+b-mod):(a+b);}
inline int dec(int a,int b){return (a<b)?(a-b+mod):(a-b);}
inline int mul(int a,int b){static ll r;r=(ll)a*b;return (r>=mod)?(r%mod):r;}
inline void Add(int &a,int b){a=(a+b)>=mod?(a+b-mod):(a+b);}
inline void Dec(int &a,int b){a=(a<b)?(a-b+mod):(a-b);}
inline void Mul(int &a,int b){static ll r;r=(ll)a*b;a=(r>=mod)?(r%mod):r;}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
inline int fix(ll x){x%=mod;return (x<0)?x+mod:x;}
cs int N=100005;
int n,X,K;
int pw[N],ip[N],a[N];
int in[N],out[N];
vector<int> e[N];
inline void init_pw(){
	pw[0]=ip[0]=1;
	for(int i=1,iv=Inv(K);i<=n;i++)pw[i]=mul(pw[i-1],K),ip[i]=mul(ip[i-1],iv);
}
int siz[N],maxn,mxsz,rt;
bool vis[N];
void getrt(int u,int fa){
	int son=0;siz[u]=1;
	for(cs int &v:e[u])if(!vis[v]&&v!=fa){
		getrt(v,u);
		siz[u]+=siz[v];
		chemx(son,siz[v]);
	}
	chemx(son,maxn-siz[u]);
	if(son<mxsz)mxsz=son,rt=u;
}
pii tu[N],td[N];
struct Map {
    static cs int mod = 19260817;
    int val[mod],adj[mod],nxt[100005],to[100005],ecnt;
    int stk[100005], top;
    inline void clear() {ecnt=0;
        while (top)
        adj[stk[top]]=0,top--;
    }
    inline void update(int p, int k) {
        int u = p % mod;
        for(int e=adj[u];e;e=nxt[e])if(to[e]==p){
        	val[e]+=k;return;
        }nxt[++ecnt]=adj[u],adj[u]=ecnt,to[ecnt]=p,val[ecnt]=k,stk[++top]=u;
    }
    inline int query(int p) {
        int u=p%mod;
        for(int e=adj[u];e;e=nxt[e])if(to[e]==p)return val[e];
        return 0;
    }
}mp1,mp2;
int tot;
void get_vl(int u,int fa,int dep,int up,int dn){
	tot++;
	up=add(mul(up,K),a[u]);
	if(dep)dn=add(dn,mul(a[u],pw[dep-1]));
	int vl=mul(dec(X,up),ip[dep+1]);
	mp1.update(vl,1),mp2.update(dn,1);
	tu[tot]=pii(vl,u);
	td[tot]=pii(dn,u);
	for(cs int &v:e[u])if(!vis[v]&&v!=fa)get_vl(v,u,dep+1,up,dn);
}
inline void calc(int u,int coef,int dep,int up,int dn=0){
	tot=1;mp1.clear(),mp2.clear();
	up=add(mul(up,K),a[u]);
	if(dep)dn=add(dn,mul(a[u],pw[dep-1]));
	tu[1]=pii(mul(dec(X,up),ip[dep+1]),u);
	td[1]=pii(dn,u);
	mp1.update(mul(dec(X,up),ip[dep+1]),1);
	mp2.update(dn,1);
	for(cs int &v:e[u])if(!vis[v])get_vl(v,u,dep+1,up,dn);
	for(int i=1;i<=tot;i++){
		in[td[i].se]+=coef*mp1.query(td[i].fi);
		out[tu[i].se]+=coef*mp2.query(tu[i].fi);
	}
}
void solve(int u,int ts){
	vis[u]=1;
	calc(u,1,0,0);
	for(cs int &v:e[u])if(!vis[v]){
		calc(v,-1,1,a[u]);
	}
	for(cs int &v:e[u])if(!vis[v]){
		if(siz[v]>siz[u])maxn=ts-siz[u];
		mxsz=1e9;
		getrt(v,rt=0);
		solve(v,maxn);
	}
}
int main(){
	#ifdef Stargazer
	freopen("lx.in","r",stdin);
	#endif
	n=read(),mod=read(),K=read(),X=read();
	init_pw();
	for(int i=1;i<=n;i++)a[i]=read();
	for(int i=1;i<n;i++){
		int u=read(),v=read();
		e[u].pb(v),e[v].pb(u);
	}
	maxn=n,mxsz=1e9;
	getrt(1,0);
	//cout<<rt<<'\n';
	solve(rt,n);
	ll ans=0;
	for(int i=1;i<=n;i++){
		ll in0=in[i],in1=n-in0,out0=out[i],out1=n-out0;
	//	cout<<in0<<" "<<in1<<" "<<out0<<" "<<out1<<'\n';
		ans+=in0*in1*2+out0*out1*2+in0*out1+in1*out0;
	}
	//cout<<ans<<'\n';
	ans/=2;
	cout<<(ll)n*n*n-ans<<'\n';
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值