20250502模拟 总结

10+100+70

T1 小w的铁路图

题目描述

对于一张 \(n\) 个节点, \(m\) 条边,没有重边和自环的有向图,边权为 \(1\) ,对于每条边,求出删掉这条边后这条边的起点到终点的最短路径长度。

数据范围

\(n \leq 10^3,m \leq 10^5\)

Solution

由于对于有边相连的两点最短路一定是连边,那么所求实际上是两点之间的次短路。
因为对于每一个点都作为起点跑一边 \(dijkstra\) ,此时同时维护最短路和次短路,并且要记录最短路路径的从起点开始到达的第一个点(因为转移次短路的时候,我们需要强制经过第一个点不同,否则会出现最后被更新为同一条路径的情况)

Code

#include<bits/stdc++.h>
#define file(x) freopen(x ".in","r",stdin),freopen(x ".out","w",stdout);
#define pb push_back
#define N 1005
#define M 100005
using namespace std;
int n,m,f[N][2],b[N][2],q[N<<1],p[N<<1],ans[N][N],u_[M],v_[M];
vector<int>t[N];
int main(){
	file("railway")
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=m;i++)cin>>u_[i]>>v_[i],t[u_[i]].pb(v_[i]);
	for(int u=1;u<=n;u++){
		int hd=1,tl=0;
		for(int i=1;i<=n;i++)for(int j=0;j<=1;j++)f[i][j]=-1,b[i][j]=0;
		for(int v:t[u])q[++tl]=v,p[tl]=0,f[v][0]=1,b[v][0]=v;
		while(hd<=tl){
			int x=q[hd],y=p[hd];hd++;
			for(int i=0;i<t[x].size();i++){
				if(t[x][i]==u)continue;
				if(f[t[x][i]][0]==-1){
					f[t[x][i]][0]=f[x][y]+1;
					b[t[x][i]][0]=b[x][y];
					q[++tl]=t[x][i],p[tl]=0;
				}else if(f[t[x][i]][1]==-1&&b[t[x][i]][0]!=b[x][y]){
					f[t[x][i]][1]=f[x][y]+1;
					b[t[x][i]][1]=b[x][y];
					q[++tl]=t[x][i],p[tl]=1;
				}
			}
		}
		for(int j=1;j<=n;j++)ans[u][j]=f[j][1];
	}
	for(int i=1;i<=m;i++)cout<<ans[u_[i]][v_[i]]<<' ';
}

T2 矩形的面积交

题目描述

平面内有 \(n\) 个已知的互不相交的矩形,每次询问给出一个矩形,求这个矩形和 \(n\) 个已知矩形的面积交之和。

数据范围

\(n,m \leq 5 \times 10^5\)

Solution

扫描线板子
但是这里给出一种别样的写法:用线段树套矩阵维护扫描过程中的区间面积和和现存线段长度和

Code

#include <bits/stdc++.h>
#define pb push_back
#define file(x) freopen(x ".in","r",stdin),freopen(x ".out","w",stdout);
#define ll long long
#define N 500005
#define mid (l+r>>1)
using namespace std;
#define getc (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
char cb[1<<15],*cs,*ct;
inline void read(int &num){ 
    char ch;while(!isdigit(ch=getc));
    for(num=ch-'0';isdigit(ch=getc);num=num*10+ch-'0');
}
int n,m,W,L_,len[N<<2];
ll ans[N],val[N<<2][3],tag[N<<2][3][3],res[3][3],res2[3],gsres;
bool lf[N<<2],tg[N<<2];
struct mdf{int y1,y2;bool f;};
vector<mdf>md[N];
struct qr{int y1,y2,num,f;};
vector<qr>q[N];
inline int ls(int p){return p<<1;}
inline int rs(int p){return p<<1|1;}
inline void f(int p,int fp){
	res2[0]=val[p][0],res2[1]=val[p][1],res2[2]=val[p][2];
	val[p][0]=val[p][1]=val[p][2]=0;
	val[p][0]=tag[fp][0][0]*res2[0]+tag[fp][0][1]*res2[1]+tag[fp][0][2]*res2[2];
	val[p][1]=tag[fp][1][0]*res2[0]+tag[fp][1][1]*res2[1]+tag[fp][1][2]*res2[2];
	val[p][2]=tag[fp][2][0]*res2[0]+tag[fp][2][1]*res2[1]+tag[fp][2][2]*res2[2];
	res[0][0]=tag[p][0][0],res[0][1]=tag[p][0][1],res[0][2]=tag[p][0][2];
	res[1][0]=tag[p][1][0],res[1][1]=tag[p][1][1],res[1][2]=tag[p][1][2];
	res[2][0]=tag[p][2][0],res[2][1]=tag[p][2][1],res[2][2]=tag[p][2][2];
	memset(tag[p],0,sizeof tag[p]);
	tag[p][0][0]+=tag[fp][0][0]*res[0][0];
	tag[p][0][1]+=tag[fp][0][0]*res[0][1];
	tag[p][0][2]+=tag[fp][0][0]*res[0][2];
	tag[p][1][0]+=tag[fp][1][0]*res[0][0];
	tag[p][1][1]+=tag[fp][1][0]*res[0][1];
	tag[p][1][2]+=tag[fp][1][0]*res[0][2];
	tag[p][2][0]+=tag[fp][2][0]*res[0][0];
	tag[p][2][1]+=tag[fp][2][0]*res[0][1];
	tag[p][2][2]+=tag[fp][2][0]*res[0][2];
	tag[p][0][0]+=tag[fp][0][1]*res[1][0];
	tag[p][0][1]+=tag[fp][0][1]*res[1][1];
	tag[p][0][2]+=tag[fp][0][1]*res[1][2];
	tag[p][1][0]+=tag[fp][1][1]*res[1][0];
	tag[p][1][1]+=tag[fp][1][1]*res[1][1];
	tag[p][1][2]+=tag[fp][1][1]*res[1][2];
	tag[p][2][0]+=tag[fp][2][1]*res[1][0];
	tag[p][2][1]+=tag[fp][2][1]*res[1][1];
	tag[p][2][2]+=tag[fp][2][1]*res[1][2];
	tag[p][0][0]+=tag[fp][0][2]*res[2][0];
	tag[p][0][1]+=tag[fp][0][2]*res[2][1];
	tag[p][0][2]+=tag[fp][0][2]*res[2][2];
	tag[p][1][0]+=tag[fp][1][2]*res[2][0];
	tag[p][1][1]+=tag[fp][1][2]*res[2][1];
	tag[p][1][2]+=tag[fp][1][2]*res[2][2];
	tag[p][2][0]+=tag[fp][2][2]*res[2][0];
	tag[p][2][1]+=tag[fp][2][2]*res[2][1];
	tag[p][2][2]+=tag[fp][2][2]*res[2][2];
	tg[p]=0;
}
inline void push_down(int p){
	if(lf[p]||tg[p])return;
	f(ls(p),p),f(rs(p),p);
	tag[p][0][0]=1,tag[p][0][1]=0,tag[p][0][2]=0;
	tag[p][1][0]=0,tag[p][1][1]=1,tag[p][1][2]=0;
	tag[p][2][0]=0,tag[p][2][1]=0,tag[p][2][2]=1;
	tg[p]=1;
}
inline void push_up(int p){
	val[p][0]=val[ls(p)][0]+val[rs(p)][0];
	val[p][1]=val[ls(p)][1]+val[rs(p)][1];
	val[p][2]=val[ls(p)][2]+val[rs(p)][2];
}
inline void build(int p,int l,int r){
	tag[p][0][0]=tag[p][1][1]=tag[p][2][2]=1,tg[p]=1;
	if(l==r)return lf[p]=1,val[p][2]=1,void();
	build(ls(p),l,mid),build(rs(p),mid+1,r);
	push_up(p);
}
inline void addsum(int p,int l,int r,int L,int R){
	if(L<=l&&r<=R)return f(p,0),void();
	push_down(p);
	if(L<=mid)addsum(ls(p),l,mid,L,R);
	if(R>mid)addsum(rs(p),mid+1,r,L,R);
	push_up(p);
}
inline void getsum(int p,int l,int r,int L,int R){
	if(L<=l&&r<=R)return gsres+=val[p][1],void();
	push_down(p);
	if(L<=mid)getsum(ls(p),l,mid,L,R);
	if(R>mid)getsum(rs(p),mid+1,r,L,R);
}
inline ll Q(int L,int R){gsres=0,getsum(1,1,W,L,R);return gsres;}
int main(){
	file("intersec")
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	read(n),read(m),read(W),read(L_),W=max(W,L_);
	for(int i=1,x1,x2,y1,y2;i<=n;i++)read(x1),read(y1),read(x2),read(y2),md[x1].pb({y1+1,y2,1}),md[x2].pb({y1+1,y2,0});
	for(int i=1,x1,x2,y1,y2;i<=m;i++)read(x1),read(y1),read(x2),read(y2),q[x1].pb({y1+1,y2,i,-1}),q[x2].pb({y1+1,y2,i,1});
	int delx=0;
	build(1,1,W);
	for(int i=0;i<=W;i++){
		if(i)delx++;
		if(!q[i].size()&&!md[i].size())continue;
		if(delx&&val[1][0]){
			tag[0][0][0]=1;
			tag[0][0][1]=0;
			tag[0][0][2]=0;
			tag[0][1][0]=delx;
			tag[0][1][1]=1;
			tag[0][1][2]=0;
			tag[0][2][0]=0;
			tag[0][2][1]=0;
			tag[0][2][2]=1;
			addsum(1,1,W,1,W);
		}
		delx=0;
		for(auto j:q[i])ans[j.num]+=j.f*Q(j.y1,j.y2);
		for(auto j:md[i])if(j.f){
			tag[0][0][0]=1;
			tag[0][0][1]=0;
			tag[0][0][2]=1;
			tag[0][1][0]=0;
			tag[0][1][1]=1;
			tag[0][1][2]=0;
			tag[0][2][0]=0;
			tag[0][2][1]=0;
			tag[0][2][2]=1;
			addsum(1,1,W,j.y1,j.y2);
		}else{
			tag[0][0][0]=1;
			tag[0][0][1]=0;
			tag[0][0][2]=-1;
			tag[0][1][0]=0;
			tag[0][1][1]=1;
			tag[0][1][2]=0;
			tag[0][2][0]=0;
			tag[0][2][1]=0;
			tag[0][2][2]=1;
			addsum(1,1,W,j.y1,j.y2);
		}
	}
	for(int i=1;i<=m;i++)cout<<ans[i]<<'\n';
}

T3 重排题

题目描述

给你一个十进制正整数 \(n\) ,你可以重新排列它的各位数字,使其成为 \(11\) 的倍数,并且要最大,而且不
能含有前导零。数据保证有解。

e.g.

\(123\) 重排可以得到 \(123,132,213,231,312,321\) ,其中 \(11\) 的倍数只有 \(132,231\) ,且 \(231\) 更大,所以输出 \(231\)

数据范围

对于 \(10\%\) 的数据: \(N \leq 10^3\)
对于 \(30\%\) 的数据: \(N \leq 10^8\)
对于 \(40\%\) 的数据: \(N \leq 10^{15}\)
对于 \(100\%\) 的数据: \(N \leq 10^{1000}\)

Solution

首先考虑贪心。从高位向低位逐位确定能否填入尽可能大的数字。
然后考虑如何判断是否可以填入这个数字。
\(11\) 的倍数的一个性质是奇数位之和与偶数位之和的差是 \(11\) 的倍数。
因此对所有的数做一个背包表示选 \(i\) 个数时对 \(11\) 取模为 \(j\) 的方案数。
然后每选一个数进行撤销背包即可。

Code

#include <bits/stdc++.h>
#define file(x) freopen(x ".in","r",stdin),freopen(x ".out","w",stdout);
#define N 1005
#define mod 1000000007
using namespace std;
string s;
int dp[N][11],tot,t[10],now=9,n,delt,sum;
inline int mo(int x){return x<mod?x:x-mod;}
inline int m1(int x){return x<11?x:x-11;}
inline void add(int x){
	for(int i=tot;~i;i--)for(int j=0;j<11;j++)dp[i+1][m1(j+x)]=mo(dp[i+1][m1(j+x)]+dp[i][j]);
	tot++,t[x]++,sum+=x;
}
inline void del(int x){
	for(int i=0;i<=tot;i++)for(int j=0;j<11;j++)dp[i+1][m1(j+x)]=mo(dp[i+1][m1(j+x)]+mod-dp[i][j]);
	tot--,t[x]--,sum-=x;
}
int main(){
	file("sort")
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>s,dp[0][0]=1,n=s.length();
	for(int i=0;i<n;i++)add(s[i]-'0');
	for(int i=1;i<=n;i++){
		while(!t[now])now--;
		for(int j=now;~j;j--)if(t[j]){
			del(j),delt+=(i&1?1:-1)*j;
			if(dp[(n-i)/2+(n&1&&!(i&1))][(6*(sum-delt)%11+11)%11]){cout<<j;break;}
			add(j),delt-=(i&1?1:-1)*j;
		}
	}
}
posted @ 2025-05-07 13:17  linjingxiang  阅读(29)  评论(0)    收藏  举报