2022杭电多校Day1

01

考虑 z 函数,对于每个 $p=G_{len}-x+1$,它能贡献的 $G_{len}$ 满足 $p\leq G_{len}< p+z[p]$ 且 $G_{len}-p+1$ 是 $k$ 的倍数,用差分维护。

Problem 01
#include<bits/stdc++.h>
//#pragma GCC optimize("O2")
using namespace std;
#define ll long long
#define pb push_back
#define mp make_pair
#define ALL(x) (x).begin(),(x).end()
#define rALL(x) (x).rbegin(),(x).rend()
#define srt(x) sort(ALL(x))
#define rev(x) reverse(ALL(x))
#define rsrt(x) sort(rALL(x))
#define sz(x) (int)(x.size())
#define inf 0x3f3f3f3f
#define pii pair<int,int>
#define lb(v,x) (int)(lower_bound(ALL(v),x)-v.begin())
#define ub(v,x) (int)(upper_bound(ALL(v),x)-v.begin())
#define uni(v) v.resize(unique(ALL(v))-v.begin())
void die(string S){puts(S.c_str());exit(0);}
void Z(char *s,int *z)
{
	int n=strlen(s);
	z[0]=0;
	for(int i=1,l=0,r=0;i<n;i++)
	{
		if(i<=r&&z[i-l]<r-i+1)
			z[i]=z[i-l];
		else
		{
			z[i]=max(0,r-i+1);
			while(i+z[i]<n&&s[z[i]]==s[i+z[i]]) z[i]++;
		}
		if(i+z[i]-1>r)
		{
			l=i;
			r=i+z[i]-1;
		}
	}
	z[0]=n;
}
char s[1001000];
int z[1001000];
int delta[2001000];
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		memset(delta,0,sizeof(delta));
		scanf("%s",s+1);
		int k,n;
		scanf("%d",&k);
		n=strlen(s+1);
		Z(s+1,z+1);
		for(int i=1;i<=n;i++)
		{
			int fst=min(n+1,i+i+k-2);
			if(z[i]+i-1<min(n+1,i+i+k-2))
				continue;
			int lst=(z[i]+i-1-min(n+1,i+i+k-2))/k*k+min(n+1,i+i+k-2);
			delta[fst]++;
			delta[lst+k]--;
		}
		ll ans=1;
		for(int i=1;i<=n;i++)
		{
			if(i>k)
				delta[i]+=delta[i-k];
			ans=ans*(delta[i]+1)%998244353;
		}
		cout<<ans<<endl;
	}
	return 0;
}

02

签到题,枚举删除了哪些墙判断联通性即可。

Problem 02
#include<bits/stdc++.h>
//#pragma GCC optimize("O2")
using namespace std;
#define ll long long
#define pb push_back
#define mp make_pair
#define ALL(x) (x).begin(),(x).end()
#define rALL(x) (x).rbegin(),(x).rend()
#define srt(x) sort(ALL(x))
#define rev(x) reverse(ALL(x))
#define rsrt(x) sort(rALL(x))
#define sz(x) (int)(x.size())
#define inf 0x3f3f3f3f
#define pii pair<int,int>
#define lb(v,x) (int)(lower_bound(ALL(v),x)-v.begin())
#define ub(v,x) (int)(upper_bound(ALL(v),x)-v.begin())
#define uni(v) v.resize(unique(ALL(v))-v.begin())
void die(string S){puts(S.c_str());exit(0);}
bool f[22][22][22][22];
pii fa[22][22];
pii fa2[22][22];
int x1[22],y1[22],x2[22],y2[22];
pii anc(pii x)
{
	if(fa[x.first][x.second]==x)
		return x;
	return fa[x.first][x.second]=anc(fa[x.first][x.second]);
}
int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie();
	cout.tie();
	int t;
	cin>>t;
	while(t--)
	{
//		memset(f,0,sizeof(f));
		int n,m,k;
		cin>>n>>m>>k;
		for(int i=0;i<n;i++)
			for(int j=0;j<m;j++)
				fa[i][j]=mp(i,j);
		int sx,sy,tx,ty;
		cin>>sx>>sy>>tx>>ty;
		for(int i=0;i<k;i++)
		{
			int x1,y1,x2,y2;
			cin>>x1>>y1>>x2>>y2;
			if(x1==x2&&y1>y2)
				swap(y1,y2);
			if(y1==y2&&x1>x2)
				swap(x1,x2);
			if(x1==x2&&x1&&x1<n)
				for(int i=y1;i<y2;i++)
					f[x1-1][i][x1][i]=1,f[x1][i][x1-1][i]=1;
			else if(y1==y2&&y1&&y1<m)
				for(int i=x1;i<x2;i++)
					f[i][y1-1][i][y1]=1,f[i][y1][i][y1-1]=1;
			::x1[i]=x1;
			::x2[i]=x2;
			::y1[i]=y1;
			::y2[i]=y2;
		}
		for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			for(int i2=max(0,i-1);i2<min(i+2,n);i2++)
			for(int j2=max(0,j-1);j2<min(j+2,m);j2++) if(abs(i-i2)+abs(j-j2)==1)
				if(!f[i][j][i2][j2])
				{
					pii p=anc(mp(i,j));
					fa[p.first][p.second]=anc(mp(i2,j2));
				}
		memcpy(fa2,fa,sizeof(fa));
		int ans=k;
		for(int msk=0;msk<(1<<k);msk++) if(__builtin_popcount(msk)<ans)
		{
			for(int i=0;i<k;i++) if(msk>>i&1)
			{
				int x1=::x1[i],y1=::y1[i],x2=::x2[i],y2=::y2[i];
				if(x1==x2&&x1&&x1<n)
					for(int i=y1;i<y2;i++)
					{
						pii p=anc(mp(x1-1,i));
						fa[p.first][p.second]=anc(mp(x1,i));
					}
				else if(y1==y2&&y1&&y1<m)
					for(int i=x1;i<x2;i++)
					{
						pii p=anc(mp(i,y1-1));
						fa[p.first][p.second]=anc(mp(i,y1));
					}
			}
			if(anc(mp(sx,sy))==anc(mp(tx,ty)))
				ans=min(ans,__builtin_popcount(msk));
			memcpy(fa,fa2,sizeof(fa));
		}
		cout<<ans<<endl;
		for(int i=0;i<k;i++)
		{
			int x1=::x1[i],y1=::y1[i],x2=::x2[i],y2=::y2[i];
			if(x1==x2&&x1&&x1<n)
				for(int i=y1;i<y2;i++)
					f[x1-1][i][x1][i]=0,f[x1][i][x1-1][i]=0;
			else if(y1==y2&&y1&&y1<m)
				for(int i=x1;i<x2;i++)
					f[i][y1-1][i][y1]=0,f[i][y1][i][y1-1]=0;
		}
	}
	return 0;
}

03

由于异或最大值不好维护,可以考虑把异或的值也记在状态里,$dp_{i,j,k}$ 表示考虑前 $i$ 个数,异或为 $j$,重量为 $k$ 是否可行,使用 bitset 来优化转移即可。

Problem 03
#include<bits/stdc++.h>
//#pragma GCC optimize("O2")
using namespace std;
#define ll long long
#define pb push_back
#define mp make_pair
#define ALL(x) (x).begin(),(x).end()
#define rALL(x) (x).rbegin(),(x).rend()
#define srt(x) sort(ALL(x))
#define rev(x) reverse(ALL(x))
#define rsrt(x) sort(rALL(x))
#define sz(x) (int)(x.size())
#define inf 0x3f3f3f3f
#define pii pair<int,int>
#define lb(v,x) (int)(lower_bound(ALL(v),x)-v.begin())
#define ub(v,x) (int)(upper_bound(ALL(v),x)-v.begin())
#define uni(v) v.resize(unique(ALL(v))-v.begin())
void die(string S){puts(S.c_str());exit(0);}
bitset<1024> f[1025][2];
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n,m;
		cin>>n>>m;
		for(int i=0;i<1025;i++)
			for(int j=0;j<1024;j++)
				f[i][0].reset(j),f[i][1].reset(j);
		f[0][0].set(0);
		int cur=0;
		while(n--)
		{
			int u,v;
			cin>>v>>u;
			for(int i=0;i<1024;i++)
				f[i][cur^1]=f[i][cur]|(f[i^u][cur]<<v);
			cur^=1;
		}
		int ans=-1;
		for(int i=0;i<1024;i++)
			if(f[i][cur][m])
				ans=i;
		cout<<ans<<endl;
	}
	return 0;
}

04

上一题是 bitset 这题肯定不是了吧……对吧……你说呢?

我的做法:

转换成切比雪夫距离求二维前缀和,枚举中位数是哪条边,答案相当于 距离 $p_1$ 长度小于中位数的点数 减去 同时距离 $p_1,p_2$ 的长度都小于中位数的点数。最后求答案时进行简单容斥即可。

官方解法:

枚举中位数,用 bitset 求答案。

Problem 04
#include<bits/stdc++.h>
//#pragma GCC optimize("O2")
using namespace std;
#define ll long long
#define pb push_back
#define mp make_pair
#define ALL(x) (x).begin(),(x).end()
#define rALL(x) (x).rbegin(),(x).rend()
#define srt(x) sort(ALL(x))
#define rev(x) reverse(ALL(x))
#define rsrt(x) sort(rALL(x))
#define sz(x) (int)(x.size())
#define inf 0x3f3f3f3f
#define pii pair<int,int>
#define lb(v,x) (int)(lower_bound(ALL(v),x)-v.begin())
#define ub(v,x) (int)(upper_bound(ALL(v),x)-v.begin())
#define uni(v) v.resize(unique(ALL(v))-v.begin())
void die(string S){puts(S.c_str());exit(0);}
int x[2020],y[2020];
vector<int> vecx,vecy;
int psum[2020][2020];
bool isprime[200200];
map<int,int> cnt;
map<pii,int> Mp;
int main()
{
	memset(isprime,1,sizeof(isprime));
	isprime[0]=isprime[1]=0;
	for(int i=2;i<=1000;i++)
		if(isprime[i])
			for(int j=i*i;j<200200;j+=i)
				isprime[j]=0;
	int t;
	scanf("%d",&t);
	while(t--)
	{
		vecx.clear();
		vecy.clear();
		memset(psum,0,sizeof(psum));
		Mp.clear();
		int n,m;
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++)
		{
			scanf("%d%d",x+i,y+i);
			int nx=x[i]+y[i];
			int ny=x[i]-y[i]+m+1;
			x[i]=nx;
			y[i]=ny;
			Mp[mp(nx,ny)]++;
			vecx.pb(x[i]);
			vecy.pb(y[i]);
		}
		vecx.pb(-1e9);
		vecy.pb(-1e9);
		srt(vecx);
		srt(vecy);
		for(int i=1;i<=n;i++)
		{
			x[i]=lb(vecx,x[i]);
			y[i]=lb(vecy,y[i]);
			psum[x[i]][y[i]]=1;
		}
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				psum[i][j]+=psum[i-1][j]+psum[i][j-1]-psum[i-1][j-1];
		ll ans=0;
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++) if(i!=j)
			{
				int distij=max(abs(vecx[x[i]]-vecx[x[j]]),abs(vecy[y[i]]-vecy[y[j]]));
				if(isprime[distij])
				{
					int lx,rx,ly,ry;
					lx=ub(vecx,vecx[x[i]]-distij);
					rx=lb(vecx,vecx[x[i]]+distij)-1;
					ly=ub(vecy,vecy[y[i]]-distij);
					ry=lb(vecy,vecy[y[i]]+distij)-1;
					rx=max(rx,lx-1);
					ry=max(ry,ly-1);
					int sum1=psum[rx][ry]-psum[lx-1][ry]-psum[rx][ly-1]+psum[lx-1][ly-1];
					int lx1,rx1,ly1,ry1;
					lx1=ub(vecx,vecx[x[j]]-distij-1);
					rx1=lb(vecx,vecx[x[j]]+distij+1)-1;
					ly1=ub(vecy,vecy[y[j]]-distij-1);
					ry1=lb(vecy,vecy[y[j]]+distij+1)-1;
					lx1=max(lx1,lx);
					ly1=max(ly1,ly);
					rx1=min(rx1,rx);
					ry1=min(ry1,ry);
					rx1=max(rx1,lx1-1);
					ry1=max(ry1,ly1-1);
					int sum2=psum[rx1][ry1]-psum[lx1-1][ry1]-psum[rx1][ly1-1]+psum[lx1-1][ly1-1];
					ans+=sum1-sum2;
				}
			}
		for(int i=1;i<=n;i++)
		{
			cnt.clear();
			for(int j=1;j<=n;j++)
			{
				int distij=max(abs(vecx[x[i]]-vecx[x[j]]),abs(vecy[y[i]]-vecy[y[j]]));
				if(isprime[distij])
					ans+=cnt[distij]++;
			}
		}
		ll ans2=0;
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++) if(i!=j)
			{
				if(x[i]==x[j])
				{
					if(y[i]>y[j])
						continue;
					int dist=vecy[y[j]]-vecy[y[i]];
					if(!isprime[dist])
						continue;
					int xx=lb(vecx,vecx[x[i]]+dist);
					if(xx<sz(vecx)&&vecx[xx]==vecx[x[i]]+dist)
						ans2+=psum[xx][y[j]-1]-psum[xx][y[i]]-psum[xx-1][y[j]-1]+psum[xx-1][y[i]];
					xx=lb(vecx,vecx[x[i]]-dist);
					if(xx<sz(vecx)&&vecx[xx]==vecx[x[i]]-dist)
						ans2+=psum[xx][y[j]-1]-psum[xx][y[i]]-psum[xx-1][y[j]-1]+psum[xx-1][y[i]];
				}
				if(y[i]==y[j])
				{
					if(x[i]>x[j])
						continue;
					int dist=vecx[x[j]]-vecx[x[i]];
					if(!isprime[dist])
						continue;
					int yy=lb(vecy,vecy[y[i]]+dist);
					if(yy<sz(vecy)&&vecy[yy]==vecy[y[i]]+dist)
						ans2+=psum[x[j]-1][yy]-psum[x[i]][yy]-psum[x[j]-1][yy-1]+psum[x[i]][yy-1];
					yy=lb(vecy,vecy[y[i]]-dist);
					if(yy<sz(vecy)&&vecy[yy]==vecy[y[i]]-dist)
						ans2+=psum[x[j]-1][yy]-psum[x[i]][yy]-psum[x[j]-1][yy-1]+psum[x[i]][yy-1];
				}
			}
//		for(int i=1;i<=n;i++)
//			cout<<vecx[x[i]]<<" "<<vecy[y[i]]<<endl;
		ll ans3=0;
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++) if(i!=j)
			{
				if(x[i]==x[j])
				{
//					cout<<"# "<<i<<" "<<j<<endl;
					int dist=abs(vecy[y[j]]-vecy[y[i]]);
					if(!isprime[dist])
						continue;
					ans3+=Mp[mp(vecx[x[i]]+dist,vecy[y[i]])];
					ans3+=Mp[mp(vecx[x[i]]-dist,vecy[y[i]])];
				}
				if(y[i]==y[j])
				{
//					cout<<"? "<<i<<" "<<j<<endl;
					int dist=abs(vecx[x[j]]-vecx[x[i]]);
					if(!isprime[dist])
						continue;
					ans3+=Mp[mp(vecx[x[i]],vecy[y[i]]+dist)];
					ans3+=Mp[mp(vecx[x[i]],vecy[y[i]]-dist)];
				}
			}
//		cout<<ans2<<" "<<ans3<<endl;
		ans-=ans2*2;
		ans-=ans3;
		printf("%lld\n",ans);
	}
	return 0;
}

05

对于每个点首先预处理它展开之后的字符串的长度(若无限长则设为 $10^{18}$)。类似于树剖的,求出每个点的重儿子,即在展开后的字符串(保留前 $10^{18}$ 个)中占的部分最长的儿子,预处理倍增数组(即每个点的第 $2^k$ 级重儿子),查询时如果在重儿子中则倍增跳,否则二分出是哪个儿子递归即可。

复杂度证明:倍增每跳一次会至少将查询区间(最初始是 $[1,10^{18}]$)减半,每次二分将会以 $\log x$ 的代价将查询区间减小到 $\frac{1}{x}$,故复杂度为 $O((n+q)\log 10^{18})$。

Problem 05
#include<bits/stdc++.h>
//#pragma GCC optimize("O2")
using namespace std;
#define ll long long
#define pb push_back
#define mp make_pair
#define ALL(x) (x).begin(),(x).end()
#define rALL(x) (x).rbegin(),(x).rend()
#define srt(x) sort(ALL(x))
#define rev(x) reverse(ALL(x))
#define rsrt(x) sort(rALL(x))
#define sz(x) (int)(x.size())
#define inf 0x3f3f3f3f
#define pii pair<int,int>
#define lb(v,x) (int)(lower_bound(ALL(v),x)-v.begin())
#define ub(v,x) (int)(upper_bound(ALL(v),x)-v.begin())
#define uni(v) v.resize(unique(ALL(v))-v.begin())
void die(string S){puts(S.c_str());exit(0);}
vector<int> G[2020];
vector<ll> vec[2020];
ll siz[2020];
char buff[100100];
const ll Max=1e18+10;
int nxt[2020][77];
ll pre[2020][77];
ll suf[2020][77];
void Assert(bool f)
{
	if(!f)
	{
		puts("fuck you,leather man~");
		exit(0);
	}
}
ll dfs(int u)
{
	if(siz[u]>0)
		return siz[u];
	if(u<=26)
	{
		siz[u]=1;
		nxt[u][0]=0;
		pre[u][0]=Max;
		suf[u][0]=Max;
		return 1;
	}
	if(siz[u]==-1)
	{
		siz[u]=Max;
		return siz[u];
	}
	siz[u]=-1;
	ll sum=0;
	ll mx=0;
	for(auto v:G[u])
	{
		ll s=dfs(v);
		s=min(s,Max-sum);
		if(s>mx)
		{
			mx=s;
			nxt[u][0]=v;
			pre[u][0]=sum;
			suf[u][0]=sum+s;
//			cout<<u<<" "<<v<<" "<<sum<<endl;
		}
		sum+=s;
		vec[u].pb(sum);
		if(sum==Max)
			break;
	}
//	Assert(vec[u].back()==sum);
	siz[u]=sum;
	return siz[u];
}
char get(int u,ll k)
{
//	Assert(k>0);
//	cout<<"-"<<u<<" "<<k<<endl;
	if(u<=26)
	{
		if(k==1)
			return (u+'a'-1);
		return '@';
	}
	if(siz[u]<k)
		return '@';
	for(int i=60;i>=0;i--)
		if(pre[u][i]<k&&suf[u][i]>=k&&nxt[u][i])
		{
//			cout<<i<<endl;
//			cout<<pre[u][i]<<endl;
//			cout<<nxt[u][i]<<endl;
			k-=pre[u][i];
			u=nxt[u][i];
		}
	if(u<=26)
	{
		if(k==1)
			return (u+'a'-1);
		return '@';
	}
	int pos=lb(vec[u],k);
	return get(G[u][pos],k-(pos>0?vec[u][pos-1]:0));
}
int main()
{
//	freopen("in.cpp","r",stdin);
	int t;
	scanf("%d",&t);
	while(t--)
	{
		memset(siz,0,sizeof(siz));
		memset(nxt,0,sizeof(nxt));
		memset(pre,0,sizeof(pre));
		memset(suf,0,sizeof(suf));
		int n,m;
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n+26;i++)
		{
			G[i].clear();
			vec[i].clear();
		}
		for(int i=1;i<=n;i++)
		{
			scanf("%s",buff);
			int len=strlen(buff);
			bool f=0;
			for(int j=0;j<len;j++)
			{
				if(buff[j]=='>')
				{
					f=1;
					continue;
				}
				if(!f)
					continue;
				if(isalpha(buff[j]))
					G[i+26].pb(buff[j]-'a'+1);
				else
				{
					Assert(buff[j]=='[');
					int p=j+1;
					int x=0;
					while(buff[p]!=']')
						x=(x<<1)+(x<<3)+(buff[p++]^48);
					G[i+26].pb(x+26);
					j=p;
				}
			}
		}
		for(int i=1;i<=n;i++)
			if(!siz[i+26])
				dfs(i+26);
		for(int i=0;i<61;i++)
			for(int j=1;j<=n+26;j++)
			{
				nxt[j][i+1]=nxt[nxt[j][i]][i];
				pre[j][i+1]=min(Max,pre[nxt[j][i]][i]+pre[j][i]);
				suf[j][i+1]=min(Max,suf[nxt[j][i]][i]+pre[j][i]);
			}
//		cout<<pre[28][59]<<endl;
//		system("pause");
//		for(int i=1;i<=n+26;i++)
//		{
//			for(auto j:G[i])
//				cout<<j<<" ";
//			puts("");
//		}
//		for(int i=1;i<=n+26;i++)
//			cout<<siz[i]<<endl;
		while(m--)
		{
			int x;
			ll k;
			scanf("%d%lld",&x,&k);
			char c=get(x+26,k);
			if(c=='@')
				printf("-1");
			else	putchar(c);
			putchar('\n');
		}
	}
	return 0;
}

08

考虑将每个点 $i$ 拆成两个点 $i$ 和 $i+n$,$i$ 表示上一步不是特殊边,$i+n$ 表示上一步是特殊边。对于正常在边上移动的转移是简单的,对于隔空 tp 的转移,我们可以发现,一个点肯定是第一次被转移到的时候最优(最短路算法一定先考虑 $dist$ 较小的点/转移)。所以可以使用 set 维护还剩哪些点没有被 tp 转移过,每次暴力转移即可。

Problem 08
#include<bits/stdc++.h>
//#pragma GCC optimize("O2")
using namespace std;
#define ll long long
#define int ll
#define pb push_back
#define mp make_pair
#define ALL(x) (x).begin(),(x).end()
#define rALL(x) (x).rbegin(),(x).rend()
#define srt(x) sort(ALL(x))
#define rev(x) reverse(ALL(x))
#define rsrt(x) sort(rALL(x))
#define sz(x) (int)(x.size())
#define inf 0x3f3f3f3f
#define pii pair<int,int>
#define lb(v,x) (int)(lower_bound(ALL(v),x)-v.begin())
#define ub(v,x) (int)(upper_bound(ALL(v),x)-v.begin())
#define uni(v) v.resize(unique(ALL(v))-v.begin())
void die(string S){puts(S.c_str());exit(0);}
int Dist[2002000];
vector<pii> G[2002000];
int nxt[2002000];
int prv[2002000];
bool f[2002000];
map<pii,bool> Mp;
int cc;
signed main()
{
	int tc;
	scanf("%lld",&tc);
	while(tc--)
	{
		Mp.clear();
		int m,n,s,k;
		scanf("%lld%lld%lld%lld",&n,&m,&s,&k);
		cc=n;
		for(int i=1;i<=n+n;i++)
			G[i].clear(),f[i]=0;
		for(int i=1;i<=n+n;i++)
			Dist[i]=1ll*inf*inf;
		while(m--)
		{
			int u,v,w,t;
			scanf("%lld%lld%lld%lld",&u,&v,&w,&t);
			if(t)
			{
				G[u+n].pb(mp(v+n,w-k));
				G[u].pb(mp(v+n,w));
			}
			else
			{
				G[u+n].pb(mp(v,w-k));
				G[u].pb(mp(v,w));
			}
			Mp[mp(u,v)]=1;
		}
		for(int i=1;i<=n;i++)
			nxt[i]=i%n+1;
		for(int i=1;i<=n;i++)
			prv[nxt[i]]=i;
		priority_queue<pii,vector<pii>,greater<pii>> pq;
		pq.push(mp(0,s));
		Dist[s]=0;
		while(!pq.empty())
		{
			int dist=pq.top().first;
			int u=pq.top().second;
			pq.pop();
			if(dist!=Dist[u])
				continue;
			if(u>n)
			{
				int x=u-n;
				int y=nxt[x];
				while(cc&&f[y])
					y=nxt[y];
				nxt[x]=y;
				if(y!=x&&!f[y])
					while(true)
					{
						if(!Mp[mp(x,y)])
						{
							if(dist<Dist[y])
							{
								Dist[y]=dist;
								pq.push(mp(dist,y));
							}
							nxt[prv[y]]=nxt[y];
							prv[nxt[y]]=prv[y];
							f[y]=1;
							cc--;
						}
						if((y-x+n)%n>=(nxt[y]-x+n)%n)
							break;
						y=nxt[y];
					}
			}
			for(auto p:G[u])
			{
				int v=p.first;
				int d=p.second;
				if(Dist[v]>dist+d)
				{
					Dist[v]=dist+d;
					pq.push(mp(Dist[v],v));
				}
			}
		}
		for(int i=1;i<=n;i++)
			if(min(Dist[i],Dist[i+n])==1ll*inf*inf)
				printf("-1 ");
			else	printf("%lld ",min(Dist[i],Dist[i+n]));
		puts("");
	}
	return 0;
}

09

不妨设 $1$ 号点一定在横线上(可以通过每次旋转 $45^\circ$ 实现),若所有点均在横线上,则答案为 YES。

否则考虑一个不在横线上的点,从它出发做竖线、左斜线、右斜线交横线为三个点,激光可以放置的点必定在这三个点中,枚举判断即可。

Problem 09
#include<bits/stdc++.h>
//#pragma GCC optimize("O2")
using namespace std;
#define ll long long
#define pb push_back
#define mp make_pair
#define ALL(x) (x).begin(),(x).end()
#define rALL(x) (x).rbegin(),(x).rend()
#define srt(x) sort(ALL(x))
#define rev(x) reverse(ALL(x))
#define rsrt(x) sort(rALL(x))
#define sz(x) (int)(x.size())
#define inf 0x3f3f3f3f
#define pii pair<int,int>
#define lb(v,x) (int)(lower_bound(ALL(v),x)-v.begin())
#define ub(v,x) (int)(upper_bound(ALL(v),x)-v.begin())
#define uni(v) v.resize(unique(ALL(v))-v.begin())
void die(string S){puts(S.c_str());exit(0);}
void turn(pii &a){a=mp(a.first-a.second,a.first+a.second);}
bool laser(pii p,pii a){return (p.first==a.first)||(p.second==a.second)||(p.first-p.second==a.first-a.second)||(p.first+p.second==a.first+a.second);}
pii pos1(pii p,pii a){return mp(p.first,a.second);};
pii pos2(pii p,pii a){return mp(p.first,a.first+a.second-p.first);};
pii pos3(pii p,pii a){return mp(p.first,p.first-a.first+a.second);};
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n;
		scanf("%d",&n);
		vector<pii> vec;
		for(int i=0;i<n;i++)
		{
			int x,y;
			scanf("%d%d",&x,&y);
			vec.pb(mp(x,y));
		}
		bool flag=0;
		for(int i=0;i<4;i++)
		{
			bool fl=1;
			for(int j=1;j<n;j++)
				if(vec[0].first!=vec[j].first)
				{
					fl=0;
					{
						bool f=1;
						pii p=pos1(vec[0],vec[j]);
						for(int x=0;x<n;x++)
							f&=laser(p,vec[x]);
						fl|=f;
					}
					{
						bool f=1;
						pii p=pos2(vec[0],vec[j]);
						for(int x=0;x<n;x++)
							f&=laser(p,vec[x]);
						fl|=f;
					}
					{
						bool f=1;
						pii p=pos3(vec[0],vec[j]);
						for(int x=0;x<n;x++)
							f&=laser(p,vec[x]);
						fl|=f;
					}
					break;
				}
			flag|=fl;
			for(auto &p:vec)
				turn(p);
		}
		if(flag)
			puts("YES");
		else	puts("NO");
	}
	return 0;
}

11

签到题,输出 \(\frac{n-m}{2}\) 即可。

Problem 11
#include<bits/stdc++.h>
//#pragma GCC optimize("O2")
using namespace std;
#define ll long long
#define pb push_back
#define mp make_pair
#define ALL(x) (x).begin(),(x).end()
#define rALL(x) (x).rbegin(),(x).rend()
#define srt(x) sort(ALL(x))
#define rev(x) reverse(ALL(x))
#define rsrt(x) sort(rALL(x))
#define sz(x) (int)(x.size())
#define inf 0x3f3f3f3f
#define pii pair<int,int>
#define lb(v,x) (int)(lower_bound(ALL(v),x)-v.begin())
#define ub(v,x) (int)(upper_bound(ALL(v),x)-v.begin())
#define uni(v) v.resize(unique(ALL(v))-v.begin())
void die(string S){puts(S.c_str());exit(0);}
int a[1001000];
const ll mod=1e9+7;
ll ksm(ll a,ll b)
{
	if(!b)
		return 1ll;
	if(b%2)
		return ksm(a*a%mod,b/2)*a%mod;
	return ksm(a*a%mod,b/2);
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		ll n,m;
		scanf("%lld%lld",&n,&m);
		cout<<(n-m)*(mod+1)/2%mod<<endl;
	}
	return 0;
}

12

考虑将数 \(i\) 看做 \(2^i\),则每次 \(-1\) 操作相当于 \(/2\),每次分裂操作也相当于 \(/2\),所以只要满足存在一个 \(k\) 使得所有 \(2^x(x\leq k)\) 的和 \(\geq 4^k\) 即为 Alice 获胜。

Problem 12
#include<bits/stdc++.h>
//#pragma GCC optimize("O2")
using namespace std;
#define ll long long
#define int ll
#define pb push_back
#define mp make_pair
#define ALL(x) (x).begin(),(x).end()
#define rALL(x) (x).rbegin(),(x).rend()
#define srt(x) sort(ALL(x))
#define rev(x) reverse(ALL(x))
#define rsrt(x) sort(rALL(x))
#define sz(x) (int)(x.size())
#define inf 0x3f3f3f3f
#define pii pair<int,int>
#define lb(v,x) (int)(lower_bound(ALL(v),x)-v.begin())
#define ub(v,x) (int)(upper_bound(ALL(v),x)-v.begin())
#define uni(v) v.resize(unique(ALL(v))-v.begin())
void die(string S){puts(S.c_str());exit(0);}
int a[1001000];
signed main()
{
	int t;
	scanf("%lld",&t);
	while(t--)
	{
		int n;
		scanf("%lld",&n);
		for(int i=0;i<=n;i++)
			scanf("%lld",a+i);
		int x=1;
		bool flag=0;
		for(int i=0;i<=n;i++)
		{
			x-=a[i];
			if(x<=0)
			{
				flag=1;
				break;
			}
			x=min(100000000000000,x+x);
		}
		if(flag)
			puts("Alice");
		else	puts("Bob");
	}
	return 0;
}

 

posted @ 2022-07-26 20:35  Kevin090228  阅读(50)  评论(0)    收藏  举报