http://192.168.14.232/contest/59

A:


创历史新低
dalao:d<=5,所以一个位置上只能是[i-d,i+d],考虑状压
ljx's code

#include <bits/stdc++.h>
using namespace std;
const int maxn=505;
const int mod=998244353;
int read(){
	int ret=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
	while( isdigit(ch)){ret=(ret<<3)+(ret<<1)+(ch&15);ch=getchar();}
	return ret*f;
}
int n,d,ans; 
int a[maxn],f[maxn][5005];
bool vis[maxn*2];
int main(){
	n=read(),d=read();
	int base=(1<<(2*d+1))-1;
	for(int i=1;i<=n;++i){
		a[i]=read();
		if(a[i]!=-1) vis[a[i]]=1;
	}
	for(int i=n+1;i<=n+d;++i) vis[i]=1;
	int in=0;
	for(int p=0-d;p<=0+d;++p){
		in<<=1;
		if(p<=0) in|=1;
		else in|=vis[p];
	}
	f[0][in]=1;
	for(int i=1;i<=n;++i){
		for(int p=0;p<=base;++p){
			int now=((p<<1)&base)|vis[i+d];
			if(a[i]!=-1){
				f[i][now]=(f[i][now]+f[i-1][p])%mod;
			}else{
				for(int t=0;t<=2*d;++t){
					if(now&(1<<t)) continue;
					f[i][now|(1<<t)]=(f[i][now|(1<<t)]+f[i-1][p])%mod;
				}
			}
		}
	}
	printf("%d\n",f[n][base]);
	return 0;
} 

B:

你会发现,原本的第一个1只会到下一个的第一个1,原本的第二个1只会到下一个的第二个1……
因此,第i个1的区间在 s1中第i个1的坐标和s2中第i个1的坐标之间
然后如果是这样:

1的区间:
[-----------]
     [---------------]
        [---------------]

显然,在一起时总贡献最大
0同理。
code:

//write as ljx's code
//%bailjx  
#include <bits/stdc++.h>
using namespace std;
inline int read(){int x=0;char ch=getchar();while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}return x;}
int n,m,cnt,ans;
int a[300005],f[300005],l[300005],r[300005];
char ch1[300005],ch2[300005];
int main(){
	n=read(),m=read();
	scanf("%s",ch1+1);
	scanf("%s",ch2+1);
	cnt=0;
	for(int i=1;i<=n+m;++i)if(ch1[i]=='1')l[++cnt]=i;
	cnt=0;
	for(int i=1;i<=n+m;++i)if(ch2[i]=='1')r[++cnt]=i;
	for(int i=1;i<=m;++i)if(r[i]<l[i]) swap(r[i],l[i]);
	for(int i=1;i<=m;++i){
		int L=1,R=i;
		while(L<R){
			int mid=(L+R)>>1;
			if(l[i]-(i-mid)<=r[mid]) R=mid;
			else L=mid+1;
		}
		f[i]=f[R-1]+(i-R);
	}
	ans+=f[m];
	cnt=0;
	for(int i=1;i<=n+m;++i){
		if(ch1[i]=='0'){
			l[++cnt]=i;
		}
	}
	cnt=0;
	for(int i=1;i<=n+m;++i)if(ch2[i]=='0')r[++cnt]=i;
	for(int i=1;i<=n;++i)if(r[i]<l[i]) swap(r[i],l[i]);
	for(int i=1;i<=n;++i){
		int L=1,R=i;
		while(L<R){
			int mid=(L+R)>>1;
			if(l[i]-(i-mid)<=r[mid]) R=mid;
			else L=mid+1;
		}
		f[i]=f[R-1]+(i-R);
	}
	ans+=f[n];
	printf("%d\n",ans);
	return 0;
} 

C:

T3 原题 ARC132E

so
nobody knows.
50pts:

//This is liujiaxin's
#include <bits/stdc++.h>
using namespace std;
const int maxn=100005;
const int mod=998244353;
int read(){
	int ret=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
	while( isdigit(ch)){ret=(ret<<3)+(ret<<1)+(ch&15);ch=getchar();}
	return ret*f;
}
int n,cnt,inv2=(mod+1)/2;
char ch[maxn];
int pos[maxn],sump[maxn],f[1005][1005];
struct BIT{
	int tree[1005];
	void add(int x,int v){
		x++;
		for(;x<=n+1;x+=x&-x) tree[x]=(tree[x]+v)%mod;
	}
	int query(int x){
		x++;
		int ret=0;
		for(;x;x-=x&-x) ret=(ret+tree[x])%mod;
		return ret;
	}
}fir[1005],sec[1005];
int quick_pow(int a,int b){
	int ret=1;
	while(b){
		if(b&1) ret=1ll*ret*a%mod;
		a=1ll*a*a%mod;b>>=1;
	}
	return ret;
}
int main(){
	n=read();
	scanf("%s",ch+1);
	for(int i=1;i<=n;++i){
		if(ch[i]=='.'){
			pos[++cnt]=i;
		}
	}
	if(cnt==n){
		printf("%d\n",1ll*n*inv2%mod);
		return 0;
	}
	pos[cnt+1]=n+1;
	for(int i=0;i<=cnt;++i){
		for(int p=pos[i]+1;p<pos[i+1];++p){
			if(ch[p]=='<'){
				f[i][i+1]++;
			}
		}
		fir[i].add(i+1,f[i][i+1]);
		sec[i+1].add(i,f[i][i+1]);
	}
	for(int i=1;i<=cnt+1;++i){
		sump[i]=(sump[i-1]+pos[i])%mod;
	}
	for(int len=2;len<=cnt+1;++len){
		int v=quick_pow(len-1,mod-2);
		for(int l=0;l+len<=cnt+1;++l){
			int r=l+len;
			f[l][r]=((sump[r-1]-sump[l]+mod)%mod-1ll*pos[l]*(len-1)%mod+mod)%mod;
			f[l][r]=(f[l][r]+(fir[l].query(r-1)-fir[l].query(l)+mod)%mod)%mod;
			f[l][r]=(f[l][r]+(sec[r].query(r-1)-sec[r].query(l)+mod)%mod)%mod;
			f[l][r]=1ll*f[l][r]*v%mod*inv2%mod;
			fir[l].add(r,f[l][r]);
			sec[r].add(l,f[l][r]);
		}
	}
	printf("%d\n",f[0][cnt+1]);
	return 0;
}

D:

只要考虑两边间的距离是否小于等于不走这条路的dis即可。
this is by ljx

#include <bits/stdc++.h>
using namespace std;
const int maxn=2005;
const long long INF=0x3f3f3f3f3f3f3f3fll;
int read(){
	int ret=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
	while( isdigit(ch)){ret=(ret<<3)+(ret<<1)+(ch&15);ch=getchar();}
	return ret*f;
}
int n,m,cnt;
long long ans;
struct line{
	int u,v,l,c;
	bool operator<(const line &B)const{return l<B.l||(l==B.l&&c<B.c);}
}p[maxn];
int fa[maxn];
int getfa(int x){return x==fa[x]?x:fa[x]=getfa(fa[x]);}
int lnk[maxn],son[maxn*2],nxt[maxn*2],w[maxn*2];
void add_e(int x,int y,int z){son[++cnt]=y;nxt[cnt]=lnk[x];lnk[x]=cnt;w[cnt]=z;}
struct node{
	int id;
	long long val;
	bool operator<(const node &B)const{return val<B.val;}
}hep[maxn];
int hep_size;
void put(int id,long long val){
	hep[++hep_size]=(node){id,val};int son=hep_size;
	while(son!=1&&hep[son]<hep[son>>1]) swap(hep[son],hep[son>>1]),son>>=1;
}
node get(){
	node ret=hep[1];hep[1]=hep[hep_size--];int fa=1,son;
	while((fa<<1)<=hep_size){
		if((fa<<1|1)>hep_size||hep[fa<<1]<hep[fa<<1|1]) son=fa<<1;else son=fa<<1|1;
		if(hep[son]<hep[fa]) swap(hep[son],hep[fa]),fa=son;else break;
	}
	return ret;
}
long long dis[maxn];
bool vis[maxn];
long long DIJ(int s,int t){
	memset(dis,0x3f,sizeof dis);
	memset(vis,0,sizeof vis);
	put(s,dis[s]=0);
	while(hep_size){
		int now=get().id;
		if(vis[now]) continue;
		vis[now]=1;
		for(int j=lnk[now];j;j=nxt[j]){
			if(dis[son[j]]>dis[now]+w[j]){
				dis[son[j]]=dis[now]+w[j];
				put(son[j],dis[son[j]]);
			}
		}
	}
	return dis[t];
}
int main(){
	n=read(),m=read();
	for(int i=1;i<=n;++i) fa[i]=i;
	for(int i=1;i<=m;++i){
		p[i].u=read();
		p[i].v=read();
		p[i].l=read();
		p[i].c=read();
	}
	sort(p+1,p+m+1);
	for(int i=1;i<=m;++i){
		int fx=getfa(p[i].u),fy=getfa(p[i].v);
		if(fx==fy) continue;
		fa[fx]=fy;
		ans+=p[i].c;
		add_e(p[i].u,p[i].v,p[i].l);
		add_e(p[i].v,p[i].u,p[i].l);
	}
	for(int i=1;i<=m;++i){
		if(DIJ(p[i].u,p[i].v)>p[i].l){
			add_e(p[i].u,p[i].v,p[i].l);
			add_e(p[i].v,p[i].u,p[i].l);
			ans+=p[i].c;
		}
	}
	printf("%lld\n",ans);
	return 0;
} 
posted @ 2024-10-20 19:26  yzc_is_SadBee  阅读(5)  评论(0编辑  收藏  举报