【比赛】高一下三调 & 高一下三调 2
十分抽象的考试和我答辩一样的成绩;
那么这就是
D1T1 李时珍的皮肤衣 100Pts
题面
皮肤衣的变化其实就是一个二进制的累加过程,因此结果就是
注意快速幂可能会炸 long long
,注意最后
点击查看代码
#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
题面
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 树,将其之前说的
也可以用 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
题面
困扰我很久的一道题...
hash + 状压 + 记忆化;
对于一个数,它原来的值和它对
所以一共只会有
我们记录一下每一种数有多少个,然后把个数存进栈里;
我们会发现,方案数仅与当前的数和剩下个数为
比如当
设
数据范围
对于每一层递归,用一个 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。
设
那么有状态转移方程
边界
建立一棵
点击查看代码
#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
题面
并查集。
将有公共质因数的几个数放在一个集合里,最后判断即可。
判断时不要判集合数量,判断每个数的
赛时因为用 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 考完后
就重测赛时一事大D特D
“上次数据范围错了不重测,这次加 Hack 重测了”
-
↑关于重测,其实这和跟谁说有关;
就不会重测赛时,但 会。 -
D2T1 和 D2T4 引发了
关于复杂度问题的大讨论
-
5.13 中午 WPC 和 GGR 同床共枕,讨论 D2T4 被宿管抓了
-
Linux 真的有俄罗斯方块!
-
事实证明我在简单题上有优势 且 只在简单题上有优势
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探