【比赛】高一下三调 & 高一下三调 2

image

十分抽象的考试和我答辩一样的成绩;

那么这就是 /2

D1T1 李时珍的皮肤衣 100Pts

题面

image

皮肤衣的变化其实就是一个二进制的累加过程,因此结果就是 (2n1+1) mod n,快速幂秒掉。

注意快速幂可能会炸 long long,注意最后 +1 也要取模。

点击查看代码
#include<bits/stdc++.h>
#include<bitset>
using namespace std;
typedef long long ll;
ll n,ans=1;
ll qp(__int128 a,ll b,ll mod){
	a%=mod;
	__int128 ans=1;
	while(b){
		if(b&1)ans=ans*a%mod;
		b>>=1;
		a=a*a%mod;
	}
	return ans;
}
int main(){
	freopen("lsz.in","r",stdin);
	freopen("lsz.out","w",stdout);
	cin>>n;
	ans=qp(2,n-1,n);
	cout<<(ans+1)%n;
	return 0;
}

D1T2 马大嘴的废话 100Pts

题面

image

in:
20
ad
ae
af
ag
ah
ai
aj
ak
al
ads
add
ade
adf
adg
adh
adi
adj
adk
adl
aes
5
b
a
d
ad
s

out:
0
20
11
11
2

对马大嘴说的废话建立 trie 树,将其之前说的 n 句话暴力拆解子串,插入 trie 树即可。

也可以用 map ,代码来自 @Elaina-0

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=21e5+5;
int n,m;
int son[N][26],word[N],tot;
string s;
map<string,bool> vis;
void insert(const string &s){
	int now=0;
	for(int i=0;i<s.size();i++){
		int ch=s[i]-'a';
		if(!son[now][ch]){
			son[now][ch]=++tot;
		}
		now=son[now][ch];	
	}
	word[now]++;
}
int query(const string &s){
	int now=0;
	for(int i=0;i<s.size();i++){
		int ch=s[i]-'a';
		if(!son[now][ch])return 0;
		else now=son[now][ch];
	}
	return word[now];
}
int main(){
	freopen("mdz.in","r",stdin);
	freopen("mdz.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		cin>>s;
		vis.clear();
		for(int k=1;k<=s.size();k++){
			for(int j=0;j<s.size()-k+1;j++){
				string s1=s.substr(j,k);
				if(vis[s1])continue;
				insert(s1);
				vis[s1]=1;
			}
		}
	}
	scanf("%d",&m);
	while(m--){
		cin>>s;
		printf("%d\n",query(s));
	}
	return 0;
}
map
#include <bits/stdc++.h>
using namespace std;
#define int long long
 
int n,q;
string s;
unordered_map<string,int> ans,p;
 
signed main(){
	freopen("mdz.in","r",stdin);
	freopen("mdz.out","w",stdout);
	
	scanf("%lld",&n);
	for(int i=1;i<=n;i++){
		cin>>s;
		p.clear();
		int len=s.size();
		for(int j=0;j<len;j++){
			string t;
			for(int k=j;k<len;k++){
				string o;
				o=s[k];
				t=t+o;
				if(!p[t]) ++ans[t],p[t]=1;
			}
		}
	}
	scanf("%lld",&q);
	while(q--){
		cin>>s;
		printf("%lld\n",ans[s]);
	}
	return 0;
}

D1T3 SSY的队列 30Pts

题面

image

困扰我很久的一道题...

hash + 状压 + 记忆化;

对于一个数,它原来的值和它对 m 取模之后的值在这道题中意义是相同的;

所以一共只会有 m 种数;

我们记录一下每一种数有多少个,然后把个数存进栈里;

我们会发现,方案数仅与当前的数和剩下个数为 x 的数有几种有关;

比如当 m=5 时,3 2 23 1 1 的结果是完全一样的;

f[i][j][k][] 表示当前为第 i 种数,剩下有 j 种个数为 1 的数,有 k 种个数为 2 的数,以此类推;

数据范围 n30,状压数组开不下,所以用哈希的思想,把状态压成一个数来计算。

对于每一层递归,用一个 map 记录即可。

要注意的是最后要乘上每一种数个数的阶乘,因为同一种数可以任意交换位置。

点击查看代码
#include<bits/stdc++.h>
using namespace std; 
typedef unsigned long long ull;
typedef long long ll;
const int N=35;
const int mod=1234567891;
const ull bas=233;
ll a[N],sta[N],b[N],n,m,tp,maxn,jc[N];
bool vis[N];
map<ull,ll> mp[N];
ll dfs(ll now,ll lat){
	if(now>n)return 1;
	memset(b,0,sizeof(b));
	for(int i=1;i<=tp;i++)if(i!=lat)b[sta[i]]++;
	ull hashs=sta[0];
	for(int i=0;i<=maxn;i++)hashs=hashs*bas+b[i];
	hashs=hashs*bas+sta[lat];
	if(mp[now].find(hashs)!=mp[now].end()) return mp[now][hashs];
	ll hh=0;
	if(sta[0]>0){
		sta[0]--;
		hh=(hh+dfs(now+1,0))%mod;
		sta[0]++;
	}
	for(int i=1;i<=tp;i++){
		if(i!=lat&&sta[i]>0){
			sta[i]--;
			hh=(hh+dfs(now+1,i))%mod;
			sta[i]++;
		}
	}
	mp[now][hashs]=hh;
	return hh;
}
int main(){
	freopen("ssy.in","r",stdin);
	freopen("ssy.out","w",stdout);
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];
	cin>>m;
	for(int i=1;i<=n;i++){
		a[i]%=m;
		if(a[i]<0)a[i]+=m;
	}
	ll ncnt=0;
	for(int i=1;i<=n;i++){
		if(vis[i])continue;
		vis[i]=1;
		ncnt=0;
		for(int j=i;j<=n;j++){
			if(a[i]==a[j]){
				vis[j]=1;
				ncnt++;
			}
		}
		maxn=max(maxn,ncnt);
		if(ncnt==1)sta[0]++;
		else sta[++tp]=ncnt;
	}
	jc[0]=1;
	for(int i=1;i<=n;i++){
		jc[i]=jc[i-1]*i%mod;
	}
	int ans=1;
	for(int i=0;i<=tp;i++){
		ans=ans*jc[sta[i]]%mod;
	}
	ans=ans*dfs(1,0)%mod;
	cout<<ans;
	return 0;
}

D1T4 清理牛棚 60Pts

题面

数据结构优化 DP。

f[x] 为清理 [L,x] 需要花费的最小代价。 把所有的奶牛的 r 进行从小到大的排序,按顺序扫描这些奶牛;

那么有状态转移方程 f[ri]=min(f[ri],min(f[x])+ci) (ai1x<bi)

边界 f[L1]=0;

建立一棵 [L,R1] 的线段树维护区间最小值即可。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
const int inf=0x3f3f3f3f;
struct tree{
	int l,r,minn;
}t[N<<2],a[N];
int n,L,R,f[N];
bool cmp(tree a,tree b){
	return a.r<b.r;
}
void pushup(int k){
	t[k].minn=min(t[k<<1].minn,t[k<<1|1].minn);
}
void build(int k,int l,int r){
	t[k]={l,r,inf};
	if(l==r)return;
	int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
}
void update(int k,int p,int val){
	if(t[k].l==t[k].r){
		t[k].minn=val;
		return;
	}
	int mid=(t[k].l+t[k].r)>>1;
	if(p<=mid)update(k<<1,p,val);
	else update(k<<1|1,p,val);
	pushup(k);
}
int query(int k,int l,int r){
	if(l<=t[k].l&&t[k].r<=r){
		return t[k].minn;
	}
	int mid=(t[k].l+t[k].r)>>1;
	if(r<=mid)return query(k<<1,l,r);
	else if(l>mid)return query(k<<1|1,l,r);
	else return min(query(k<<1,l,r),query(k<<1|1,l,r));
}
int main(){
	freopen("clean.in","r",stdin);
	freopen("clean.out","w",stdout);
	cin>>n>>L>>R;
	L++;R++;
	memset(f,0x3f,sizeof(f));
	for(int i=1;i<=n;i++){
		cin>>a[i].l>>a[i].r>>a[i].minn;
		a[i].l++;a[i].r++;
		a[i].l=max(a[i].l,L);
		a[i].r=min(a[i].r,R);	
	}
	build(1,L-1,R);
	update(1,L-1,0);
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n;i++){
		f[a[i].r]=min(f[a[i].r],query(1,a[i].l-1,a[i].r)+a[i].minn);
		update(1,a[i].r,f[a[i].r]);
	}
	if(f[R]==inf)f[R]=-1;
	cout<<f[R];
	return 0;
}

D1T5 历史研究 46Pts

题面

回滚莫队板子,但打错了。

也可以用分块过去,代码来自@qinyun

点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int n,m;
struct Query{
	int l,r,id;
}Q[N];
int poi[N],cnt[N];
vector<int> nums;
ll ans[N];
int block;
inline int get(int x){
	return x/block;
}
bool cmp(Query a,Query b){
	int al=get(a.l),bl=get(b.l);
	if(al!=bl) return al<bl;
	return a.r<b.r;
}
void add(int &x,ll &res){
	cnt[x]++;
	res=max(res,(ll)cnt[x]*nums[x]);
}
int main(){
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i){
		scanf("%d",&poi[i]);
		nums.push_back(poi[i]);
	}
	sort(nums.begin(),nums.end());
	nums.erase(unique(nums.begin(),nums.end()),nums.end());
	for(int i=1;i<=n;i++){
		poi[i]=lower_bound(nums.begin(),nums.end(),poi[i])-nums.begin();
	}
	for(int i=1;i<=m;i++){
		int l,r;
		scanf("%d%d",&l,&r);
		Q[i]={l,r,i};
	}
	block=sqrt(n);
	sort(Q+1,Q+1+m,cmp);
	for(int x=1;x<=m;){
		int y=x;
		while(y<=m&&get(Q[y].l)==get(Q[x].l))y++;
		int right=get(Q[x].l)*block+block-1;
		while(x<y&&Q[x].r<=right){
			ll res=0;
			int id=Q[x].id,l=Q[x].l,r=Q[x].r;
			for(int k=l;k<=r;k++)add(poi[k],res);
			ans[id]=res;
			for(int k=l;k<=r;k++)--cnt[poi[k]];
			++x;
		}
		ll res=0;
		int l=right+1,r=right;
		while(x<y){
			int id=Q[x].id,L=Q[x].l,R=Q[x].r;
			while(r<R)add(poi[++r],res);
			ll back=res;
			while(l>L)add(poi[--l],res);
			ans[id]=res;
			while(l<right+1)--cnt[poi[l++]];
			res=back;
			++x;
		}
		memset(cnt,0,sizeof(cnt));
	}
	for(int i=1;i<=m;i++) printf("%lld\n",ans[i]);
	return 0;
}
分块
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

inline int read()
{
	int ans=0;char ch=getchar();
	while(ch<'0' || ch>'9')ch=getchar();
	while(ch>='0' && ch<='9'){ans=(ans<<1)+(ans<<3)+(ch^48);ch=getchar();}
	return ans;
}

void print(ll n)
{
	if(n>9)print(n/10);
	putchar(n%10+'0');
}

const int maxt=200;
const int maxn=1e5+50;

unordered_map<int,int>ump;
int rk[maxn],a[maxn];

int st[maxt],ed[maxt],pos[maxn];
ll sum[maxt][maxn],mx[maxt][maxt];
inline void prepare(int n,int q)
{
	int len=pow(n,0.62);
	int t=n/len;
	st[1]=1,ed[1]=len;
	for(register int i=2;i<=t;++i)
	  st[i]=ed[i-1]+1,ed[i]=ed[i-1]+len;
	ed[t]=n;
	
	for(register int i=1;i<=t;++i)
	  for(register int j=st[i];j<=ed[i];++j)
	    pos[j]=i;
	    
	for(register int i=1;i<=n;++i)
	  for(register int j=pos[i];j<=t;++j)
	  {
	  	sum[j][rk[i]]+=a[i];
	  	for(register int k=1;k<=pos[i];++k)
	  		mx[k][j]=max(mx[k][j],sum[j][rk[i]]-sum[k-1][rk[i]]);
	  }
}

ll tmp[maxn],ans;
inline ll query(int l,int r)
{
	ans=0;
	int p=pos[l],q=pos[r];
	
	if(q-p<=1)
	{
		for(register int i=l;i<=r;++i)
		{
			tmp[rk[i]]+=a[i];
			ans=max(ans,tmp[rk[i]]);
		}
		for(register int i=l;i<=r;++i)
			tmp[rk[i]]=0;
		return ans;
	}
	
	ans=mx[p+1][q-1];
	for(register int i=l;i<=ed[p];++i)
	{
		sum[p][rk[i]]-=a[i];
		ans=max(ans,sum[q-1][rk[i]]-sum[p][rk[i]]);
	}
	
	for(register int i=st[q];i<=r;++i)
	{
		sum[q-1][rk[i]]+=a[i];
		ans=max(ans,sum[q-1][rk[i]]-sum[p][rk[i]]);
	}
	
	for(register int i=l;i<=ed[p];++i)
		sum[p][rk[i]]+=a[i];
	for(register int i=st[q];i<=r;++i)
		sum[q-1][rk[i]]-=a[i];

	return ans;
}


int main()
{
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);

	int n=read(),q=read();
	for(register int i=1;i<=n;++i)
	  rk[i]=a[i]=read();
	
	sort(rk+1,rk+1+n);
	int len=unique(rk+1,rk+1+n)-(rk+1);
	for(register int i=1;i<=len;++i)ump[rk[i]]=i;
	for(register int i=1;i<=n;++i)rk[i]=ump[a[i]];
	
	prepare(n,q);
	
	int l,r;
	for(register int i=1;i<=q;++i)
	{
		l=read(),r=read();
		print(query(l,r));
		putchar('\n');
	}
	return 0;
}

D2T1 攻击装置 100Pts

题面

二分图板子,最大独立集。

在可以互相攻击的两个点间连一条边。

注意 vector 会被卡 T。

赛事因为数组开小了痛失 1h,望周知。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=205;
struct edge{
	int next,to;
}e[N*N*8];
int h[N*N],cnt;
void add(int u,int v){
	e[++cnt]={h[u],v};
	h[u]=cnt;
}
int n,tot=0;
struct node{
	int id,ok;
}a[N][N];
int x[8]={-1,-2,1,2,-1,-2,1,2},y[8]={-2,-1,-2,-1,2,1,2,1};
int vis[N*N],mat[N*N];
int dfs(int x){
	for(int i=h[x];i;i=e[i].next){
		int to=e[i].to;
		if(!vis[to]){
			vis[to]=1;
			if(!mat[to]||dfs(mat[to])){
				mat[to]=x;
				return 1;
			}
		}
	}
	return 0;
}
int main(){
	freopen("attack.in","r",stdin);
	freopen("attack.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			scanf("%1d",&a[i][j].ok);
			if(!a[i][j].ok)a[i][j].id=++tot;
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(!a[i][j].ok){
				for(int k=0;k<8;k++){
					int xx=i+x[k],yy=j+y[k];
					if(xx>=1&&xx<=n&&yy>=1&&yy<=n){
						if(!a[xx][yy].ok){
							int p=a[i][j].id,q=a[xx][yy].id;
							add(p,q);
						}
					}
				}
			}
		}
	}
	int ans=0;
	for(int i=1;i<=tot;i++){
		memset(vis,0,sizeof(vis));
		ans+=dfs(i);
	}
	cout<<tot-ans/2;
	return 0;
}

D2T2 循环 100Pts

题面

暴力模拟即可。

听说都不用快速幂。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll x;
unordered_map<int,bool> vis;
ll qp(ll a,ll b,ll mod){
	ll ans=1;
	a%=100;
	while(b){
		if(b&1)ans=ans*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return ans;
}
int main(){
	freopen("number.in","r",stdin);
	freopen("number.out","w",stdout);
	cin>>x;
	for(int i=1;;i++){
		ll res=qp(x,i,100);
		if(vis[res]){
			cout<<res;
			break;
		}
		vis[res]=1;
		cout<<res<<" ";
	}
	return 0;
}

D2T3 漫步 100Pts

题面

显然,如果一个人前面有比他还慢的人,那么这两个人最后一定会合并起来。

正解是单调栈,从前到后扫过去即可,代码来自@Peppa_Even_Pig

我赛时用的线段树维护最小值。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
ll e[N];
ll x;
ll n;
struct tree{
	ll l,r,minn;
}t[N<<2];
void pushup(int k){
	t[k].minn=min(t[k<<1].minn,t[k<<1|1].minn);
}
void build(int k,int l,int r){
	t[k]={l,r,e[l]};
	if(l==r)return;
	int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	pushup(k);
}
int query(int k,int l,int r){
	if(l<=t[k].l&&t[k].r<=r)return t[k].minn;
	int mid=(t[k].l+t[k].r)>>1;
	int res=INT_MAX;
	if(l<=mid)res=min(res,query(k<<1,l,r));
	if(r>mid)res=min(res,query(k<<1|1,l,r));
	return res;
}
int main(){
	freopen("jog.in","r",stdin);
	freopen("jog.out","w",stdout);
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>x>>e[i];
	}
	build(1,1,n);
	ll ans=n;
	for(int i=1;i<=n;i++){
		ll minn=query(1,i+1,n);
		if(e[i]>minn)ans--;
	}
	cout<<ans;
	return 0;
}
单调栈
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
priority_queue<int> q;
int n;
int main() {
	freopen("jog.in", "r", stdin);
	freopen("jog.out", "w", stdout);
	cin >> n;
	int a, b;
	for (int i = 1; i <= n; i++) {
		cin >> a >> b;
		while(!q.empty() && b < q.top()) q.pop();
		q.push(b);
	}
	cout << q.size();
	return 0;
}

D2T4 穿越 40Pts

题面

BFS 或 Dijikstra(或 DP)

赛时没时间直接跳了,只打了 20% 但得了 40% (足以证明数据有多水)(其实水点挺好的)

三种方法好像都能被卡掉,暂无 Hack 数据。

赛后写的是题解的 BFS + Dijikstra(?);

BFS 代码来自@GGrun-sum,Dijikstra 代码来自@qinyun,DP 代码来自@Peppa_Even_Pig

update:赛后 lxyt-415x 加了一组卡正确性的 hack,卡掉了所有不判时间的 BFS
晓飞谷又重测了赛时导致我下去了一名 : (

点击查看代码(似了)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=1005;
int dx[4]={0,0,-1,1},dy[4]={1,-1,0,0};
int n,m,p,r,b;
int rain[N][N];
int mp[N][N],dis[N][N];
int wke[N][N],slp[N][N];
vector<pii>tp;
bool judge(int x,int y){
    return(x<=n&&x>=1&&y<=m&&y>=1&&mp[x][y]!=1);
}
void bfs(){
	memset(dis,0x3f,sizeof(dis));
    queue<pii>q;
    dis[1][1]=0;
    q.push({1,1});
    while(!q.empty()){
        pii p=q.front();
		q.pop();
        int x=p.first,y=p.second;
        for(int i=0;i<4;i++){
            int posx=x+dx[i],posy=y+dy[i];
            if(judge(posx,posy)&&mp[posx][posy]!=1){
                if(mp[posx][posy]==0){
                    if(dis[x][y]+1<rain[posx][posy]&&dis[posx][posy]>dis[x][y]+1){
                        dis[posx][posy]=dis[x][y]+1;
                        q.push({posx,posy});
                    }
                }
                else if(mp[posx][posy]==2){
                    if(dis[x][y]+1<rain[posx][posy]){
                        int f=0;
                        if(dis[x][y]+1>=wke[posx][posy]&&dis[x][y]+1<=slp[posx][posy]) f=1;
                        if(f){
                            if(dis[posx][posy]>slp[posx][posy]+1&&slp[posx][posy]+1<rain[posx][posy]){
                                dis[posx][posy]=slp[posx][posy]+1;
                                q.push({posx,posy});
                            }
                        }
                        else{
                            if(dis[posx][posy]>dis[x][y]+1){
                                dis[posx][posy]=dis[x][y]+1;
                                q.push({posx,posy});
                            }
                        }
                    }
                }
                else if(mp[posx][posy]==3){
                    if(dis[x][y]+1<rain[posx][posy]&&dis[posx][posy]>dis[x][y]+1){///当前不会被冲刷
                        dis[posx][posy]=dis[x][y]+1;
                        q.push({posx,posy}); 
                    }
                    if(dis[x][y]+1<rain[posx][posy]){
                        for(auto &j:tp){
                            int tpx=j.first,tpy=j.second;
                            if(dis[x][y]+3<rain[tpx][tpy]&&dis[x][y]+3<dis[tpx][tpy]){
                                dis[tpx][tpy]=dis[x][y]+3;
                                q.push({tpx,tpy});
                            }
                        }
                    }
                }
            }
        }
    }
}
int main(){
    freopen("cross.in","r",stdin);
    freopen("cross.out","w",stdout);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            cin>>mp[i][j];
            if(mp[i][j]==3)tp.push_back({i,j});
            rain[i][j]=0x3f3f3f3f;
        }
    cin>>p;
    int tt,a,x,y;
    for(int i=1;i<=p;i++){
        cin>>tt>>a;
        for(int j=1;j<=a;j++){
            cin>>x>>y;
            if(tt<rain[x][y])rain[x][y]=tt;
        }
    }
    cin>>p;
    for(int i=1;i<=p;i++){
        int t1,t2;
        cin>>t1>>t2>>x>>y;
        wke[x][y]=t1;
        slp[x][y]=t2;
    }
    bfs();
    cout<<dis[n][m];
    return 0;
}
BFS(没似)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define mk make_pair
#define ps push_back
#define fi first
#define se second
const int N=350;
int n,m,t,f[N][N],a,b,xia[N][N];
vector<pii> q[N][N],ch;
queue<pair<pii,int> > qq;
bool vis[N][N];
inline void jia(int x,int y,int t){
	if(x<=0||x>n||y<=0||y>m||vis[x][y]||f[x][y]==1||t>=xia[x][y])return;
	if(f[x][y]!=2){
		qq.push({{x,y},t});
		vis[x][y]=1;
		if(x==n&&y==m){
			cout<<t;exit(0);
		}
	}
	else{
		for(auto i:q[x][y]){
			if(i.fi<=t&&i.se>=t)return;
		}
		qq.push({{x,y},t});
		vis[x][y]=1;
	}
}
int main(){
	freopen("cross.in","r",stdin);
	freopen("cross.out","w",stdout);
	scanf("%d%d",&n,&m);
	memset(xia,0x7f,sizeof(xia));
	int x,y,z;
	for(int i=1;i<=n;++i){
		for(int j=1;j<=m;++j){
			scanf("%d",&f[i][j]);
			if(f[i][j]==3)ch.ps({i,j});
		}
	}
	scanf("%d",&a);
	for(int i=1;i<=a;++i){
		scanf("%d%d",&b,&x);
		for(int j=1;j<=x;++j){
			scanf("%d%d",&y,&z);
			xia[y][z]=min(xia[y][z],b);
		}
	}
	scanf("%d",&b);
	for(int i=1;i<=b;++i){
		scanf("%d%d%d%d",&a,&x,&y,&z);
		q[y][z].ps({a,x});
	}
	qq.push({{1,1},0});vis[1][1]=1;
	while(1){
		pii k=qq.front().fi;
		int x=k.fi,y=k.se,t=qq.front().se;qq.pop();
		vis[x][y]=0;
		jia(x+1,y,t+1);jia(x-1,y,t+1),jia(x,y+1,t+1),jia(x,y-1,t+1);jia(x,y,t+1);
		if(f[x][y]==3){
			for(auto j:ch)jia(j.fi,j.se,t+2);
		}
	}
}
Dijikstra(似了)
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
#define re register

ll read()
{
	ll ans=0;bool f=0;char ch=getchar();
	while(ch<'0' || ch>'9'){if(ch=='-')f=1;ch=getchar();}
	while(ch>='0' && ch<='9'){ans=(ans<<1)+(ans<<3)+(ch^48);ch=getchar();}
	return f?~ans+1:ans;
}

void print(ll n)
{
	if(n<0)putchar('-'),n=-n;
	if(n>9)print(n/10);
	putchar(n%10+48);
}

int n,m;
int mp[350][350];
int lt_rain[350][350];
vector<pair<int,int>>vc[350][350],ch;
priority_queue<pair<int,pair<int,int>>>pq;
int d[350][350],dx[10]={0,1,-1,0,0},dy[10]={0,0,0,1,-1};

inline bool check(int v,int x,int y)
{
	int t1,t2;
	for(re auto it:vc[x][y])
	{
		t1=it.first,t2=it.second;
		if(v>=t1 and v<=t2)return 1;
	}
	return 0;
}

int dj()
{
	memset(d,0x3f,sizeof d);
	d[1][1]=0;
	pq.push({0,{1,1}});
	int x,y,tx,ty;
	pair<int,int>it;
	while(!pq.empty())
	{
		it=pq.top().second;
		pq.pop();
		x=it.first,y=it.second;
		if(x==n and y==m)return d[x][y];
		for(int i=1;i<=4;++i)
		{
			tx=x+dx[i],ty=y+dy[i];
			
			if(tx<=0 || tx>n || ty<=0 || ty>m)continue;
			if(d[x][y]+1>=lt_rain[tx][ty])continue;
			if(mp[tx][ty]==1)continue;
			
			if( (mp[tx][ty]==0 || mp[tx][ty]==3) and d[x][y]+1<d[tx][ty])
			{
				d[tx][ty]=d[x][y]+1;
				pq.push({-d[tx][ty],{tx,ty}});
			}
			else if(mp[tx][ty]==2 and d[x][y]+1<d[tx][ty])
			{
				if(check(d[x][y]+1,tx,ty))
				{
					if( d[x][y]+1<lt_rain[x][y] and ( mp[x][y]!=2 || check(d[x][y]+1,tx,ty) ) )
					{
						++d[x][y];
						pq.push({-d[x][y],{x,y}});
					}
				}
				else
				{
					d[tx][ty]=d[x][y]+1;
					pq.push({-d[tx][ty],{tx,ty}});
				}
			}
		}
		if(mp[x][y]==3)
		  for(re auto it:ch)
		  {
		  	tx=it.first,ty=it.second;
		  	if(d[x][y]+2>=lt_rain[tx][ty])continue;
			if(d[x][y]+2<d[tx][ty])
			{
				d[tx][ty]=d[x][y]+2;
				pq.push({-d[tx][ty],{tx,ty}});
			}
		  }
	}
	return d[n][m];
}

int main() {
	freopen("cross.in","r",stdin);
	freopen("cross.out","w",stdout);
	
	n=read(),m=read();
	for(int i=1;i<=n;++i)
	  for(re int j=1;j<=m;++j)
	    mp[i][j]=read();
	
	for(int i=1;i<=n;++i)
	  for(re int j=1;j<=m;++j)
	    if(mp[i][j]==3)
	      ch.push_back({i,j});
	
	memset(lt_rain,0x3f,sizeof lt_rain);
	
	int a=read(),t,p,x,y;
	for(int i=1;i<=a;++i)
	{
		t=read(),p=read();
		while(p--)
		{
			x=read(),y=read();
			lt_rain[x][y]=min(lt_rain[x][y],t);
		}
	}
	
	int b=read(),t1,t2;
	for(re int i=1;i<=b;++i)
	{
		t1=read(),t2=read(),x=read(),y=read();
		vc[x][y].push_back({t1,t2});
	}
	
	print(dj());
	
	return 0;
}
DP(似了)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
vector<pair<int, int> > v;
int n, m, b, c;
int a[505][505];
int f[505][505];
int yu[505][505];
struct sss{
	int l, r, cnt;
}shou[505][505][505];
int main() {
	freopen("cross.in", "r", stdin);
	freopen("cross.out", "w", stdout);
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			scanf("%d", &a[i][j]);
		}
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (a[i][j] == 3) v.push_back({i, j});
		}
	}
	scanf("%d", &b);
	int t, p, x, y;
	for (int i = 1; i <= b; i++) {
		scanf("%d %d", &t, &p);
		for (int j = 1; j <= p; j++) {
			scanf("%d %d", &x, &y);
			yu[x][y] = t;
		}
	}
	scanf("%d", &c);
	int t1, t2;
	for (int i = 1; i <= c; i++) {
		scanf("%d %d %d %d", &t1, &t2, &x, &y);
		shou[x][y][++shou[x][y][0].cnt].l = t1;
		shou[x][y][shou[x][y][0].cnt].r = t2;
	}
	memset(f, 0x3f, sizeof(f));
	f[1][1] = 0;
	int tt = 2;
	while(tt--)
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (i == 1 && j == 1) continue;
			if (a[i][j] == 0) {
				int mi = min({f[i - 1][j] + 1, f[i][j - 1] + 1, f[i + 1][j] + 1, f[i][j + 1] + 1, f[i][j]});
				if (yu[i][j] == 0) {
					f[i][j] = mi;
				} else {
					if (yu[i][j] <= mi) {
						f[i][j] = 0x3f3f3f3f;
					} else {
						f[i][j] = mi;
					}
				}
			}
			if (a[i][j] == 2) {
				int mi = min({f[i - 1][j] + 1, f[i][j - 1] + 1, f[i + 1][j] + 1, f[i][j + 1] + 1, f[i][j]});
				if (yu[i][j] != 0) {
					if (yu[i][j] <= mi) {
						f[i][j] = 0x3f3f3f3f;
						continue;
					}
				}
				if (shou[i][j][0].cnt == 0) {
					f[i][j] = mi;
				} else {
					bool v = true;
					for (int k = 1; k <= shou[i][j][0].cnt; k++) {
						if (mi >= shou[i][j][k].l && mi <= shou[i][j][k].r) {
							v = false;
							if (shou[i][j][k].r + 1 >= yu[i][j] && yu[i][j] != 0) {
								f[i][j] = 0x3f3f3f3f;
								break;
							}
							f[i][j] = shou[i][j][k].r + 1;
							break;
						}
					}
					if (v) {
						f[i][j] = mi;
					}
				}
			}
			if (a[i][j] == 3) {
				int mi = min({f[i - 1][j] + 1, f[i][j - 1] + 1, f[i + 1][j] + 1, f[i][j + 1] + 1, f[i][j]});
				for (int k = 0; k < v.size(); k++) {
					int xx = v[k].first;
					int yy = v[k].second;
					mi = min(mi, f[xx][yy] + 2);
				}
				if (yu[i][j] == 0) {
					f[i][j] = mi;
				} else {
					if (yu[i][j] <= mi) {
						f[i][j] = 0x3f3f3f3f;
					} else {
						f[i][j] = mi;
					}
				}
			}
		}
	}
	printf("%d", f[n][m]);
	return 0;
}

D2T5 结队 10Pts

题面

并查集。

将有公共质因数的几个数放在一个集合里,最后判断即可。

判断时不要判集合数量,判断每个数的 fa 是否还是它自己。

赛时因为用 set 判集合数量导致小样例一直没过,于是 pass 了并查集做法,糊了一个假的线段树合并。

代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e4+5;
int a,b,pp,fa[N];
int prim[N];
vector<int> p;
int find(int x){
	if(x!=fa[x])fa[x]=find(fa[x]);
	return fa[x];
}
int main(){
	freopen("merge.in","r",stdin);
	freopen("merge.out","w",stdout);
	cin>>a>>b>>pp;
	for(int i=a;i<=b;i++)fa[i]=i;
	for(int i=2;i<=b;i++){
		if(prim[i])continue;
		for(int j=2;j*i<=b;j++){
			prim[i*j]=1;
		}
	}
	for(int i=pp;i<=b;i++)if(!prim[i])p.push_back(i);
	for(auto &i:p){
		int j=i;
		while(j<a)j+=i;
		int now=find(j);
		for(j;j<=b;j+=i)fa[find(j)]=now;
	}
	int ans=0;
	for(int i=a;i<=b;i++)if(i==fa[i])ans++;
	cout<<ans;
	return 0;
}

后记

  • 凭什么 D2 rk1~rk5 有冰棍?

  • 膜拜 GGR,膜拜 qinyun,膜拜 JD,膜拜 PEP,膜拜 9G,膜拜WPC,膜拜所有在我前面的

  • D1 考完后 JD 就重测赛时一事大D特D 晓飞谷

“上次数据范围错了不重测,这次加 Hack 重测了”

  • ↑关于重测,其实这和跟谁说有关;Huge 就不会重测赛时,但 晓飞谷 会。

  • D2T1 和 D2T4 引发了关于复杂度问题的大讨论

  • 5.13 中午 WPC 和 GGR 同床共枕,讨论 D2T4 被宿管抓了

  • Linux 真的有俄罗斯方块!

  • 事实证明我在简单题上有优势 且 只在简单题上有优势

posted @   萝卜甜了  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探
点击右上角即可分享
微信分享提示