10.22 模拟赛
水平太菜暴力写挂被汪神踩的一次考试 耻辱#2
T1 game
题目大意:
有一个n×n的01方格,要从中选出一个面积最大的矩形区域,要求这个矩形区域不能有超过k个1 输出这个面积
思路:
枚举起点后 再枚举一维长度 可以发现另一维长度是单调的
n三方暴力即可
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #define inf 2139062143 11 #define ll long long 12 #define MAXN 510 13 using namespace std; 14 inline int read() 15 { 16 int x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();} 18 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 19 return x*f; 20 } 21 int n,k,sum[MAXN][MAXN],ans; 22 int main() 23 { 24 freopen("game.in","r",stdin); 25 freopen("game.out","w",stdout); 26 n=read(),k=read(); 27 for(register int i=1;i<=n;i++) 28 for(register int j=1;j<=n;j++) 29 sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+read(); 30 for(register int i=1;i<=n;i++) 31 for(register int j=1;j<=n;j++) 32 for(register int tmp,t=i,st=n;t<=n;t++) 33 { 34 tmp=sum[t][st]-sum[i-1][st]-sum[t][j-1]+sum[i-1][j-1]; 35 while(tmp>k&&st>j) st--,tmp=sum[t][st]-sum[i-1][st]-sum[t][j-1]+sum[i-1][j-1]; 36 ans=max(ans,(t-i+1)*(st-j+1)); 37 } 38 printf("%d",ans); 39 }
T2 design
题目大意:
n座城市组成一棵树 需要在这 n 座城市选出若干座城市建立机场,每座城市建立机场有不同的代价
建立机场之后,每座城市得到补给的代价为该城市到最近机场的距离
总共花费的代价即为建立机场的代价与每座城市得到补给的代价之和 求这个最小代价
思路:
考试的时候没想到正解 打了30分暴力和40分链(链还写挂了10分)
正解为树形dp
dp i j表示指定离i最近点为j子树的代价
转移时非常好转移(但是想不到 还是太菜了)
g x 表示 f x i 中的最小值
答案为g 1(王爷的标程)
1 #include<cstdio> 2 #include<cstring> 3 #include<cctype> 4 #include<cmath> 5 #include<algorithm> 6 #define rep(i,s,t) for(int i=s;i<=t;i++) 7 #define dwn(i,s,t) for(int i=s;i>=t;i--) 8 using namespace std; 9 inline int read() { 10 int x=0,f=1;char c=getchar(); 11 for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; 12 for(;isdigit(c);c=getchar()) x=x*10+c-'0'; 13 return x*f; 14 } 15 typedef long long ll; 16 const int maxn=2610; 17 int n,cost[maxn],first[maxn],nxt[maxn<<1],to[maxn<<1],dis[maxn<<1],e; 18 void AddEdge(int u,int v,int w) { 19 to[++e]=v;dis[e]=w;nxt[e]=first[u];first[u]=e; 20 to[++e]=u;dis[e]=w;nxt[e]=first[v];first[v]=e; 21 } 22 int dist[maxn][maxn]; 23 void dfs(int x,int fa,int s) { 24 for(int i=first[x];i;i=nxt[i]) if(to[i]!=fa) dist[s][to[i]]=dist[s][x]+dis[i],dfs(to[i],x,s); 25 } 26 int f[maxn][maxn],g[maxn]; 27 void dp(int x,int fa) { 28 for(int i=first[x];i;i=nxt[i]) if(to[i]!=fa) dp(to[i],x); 29 rep(j,1,n) { 30 f[x][j]=cost[j]+dist[x][j]; 31 for(int i=first[x];i;i=nxt[i]) if(to[i]!=fa) f[x][j]+=min(g[to[i]],f[to[i]][j]-cost[j]); 32 } 33 g[x]=f[x][1]; 34 rep(i,2,n) g[x]=min(g[x],f[x][i]); 35 } 36 int main() { 37 freopen("design.in","r",stdin); 38 freopen("design.out","w",stdout); 39 n=read(); 40 rep(i,1,n) cost[i]=read(); 41 rep(i,1,n-1) { 42 int u=read(),v=read(),w=read(); 43 AddEdge(u,v,w); 44 } 45 rep(i,1,n) dfs(i,0,i); 46 dp(1,0); 47 printf("%d\n",g[1]); 48 return 0; 49 }
T3 trip
题目大意:
数轴上有一些点x i 每个点x i 可以花费 t i 走到 x i-w i -- x i+w i 任意一点
求从s走到t的最小时间
思路:
线段树优化建图
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #define inf 2139062143 11 #define ll long long 12 #define MAXN 200010 13 using namespace std; 14 inline int read() 15 { 16 int x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();} 18 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 19 return x*f; 20 } 21 int n,s,t,v[MAXN],id[MAXN],vis[MAXN<<2],x[MAXN],w[MAXN]; 22 int nxt[MAXN*60],fst[MAXN*60],to[MAXN*60],val[MAXN*60],cnt; 23 void add(int u,int v,int w) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w;} 24 void build(int k,int l,int r) 25 { 26 if(l==r) {id[l]=k;return ;} 27 int mid=l+r>>1; 28 add(k,k<<1,0);add(k,k<<1|1,0); 29 build(k<<1,l,mid);build(k<<1|1,mid+1,r); 30 } 31 void mdf(int k,int l,int r,int a,int b,int t) 32 { 33 if(l==a&&r==b) {add(id[t],k,v[t]);return ;} 34 int mid=l+r>>1; 35 if(b<=mid) mdf(k<<1,l,mid,a,b,t); 36 else if(a>mid) mdf(k<<1|1,mid+1,r,a,b,t); 37 else {mdf(k<<1,l,mid,a,mid,t);mdf(k<<1|1,mid+1,r,mid+1,b,t);} 38 } 39 struct node{int x;ll dis;}; 40 bool operator < (node a,node b) {return a.dis>b.dis;} 41 ll dis[MAXN<<2]; 42 priority_queue <node> q; 43 inline ll dij() 44 { 45 int a; 46 for(int i=1;i<=id[n];i++) dis[i]=2147483647000000000LL; 47 memset(dis,127,sizeof(dis)); 48 dis[id[s]]=0;q.push((node){id[s],dis[id[s]]}); 49 while(!q.empty()) 50 { 51 a=q.top().x;q.pop();if(vis[a]) continue; 52 vis[a]=1; 53 for(int i=fst[a];i;i=nxt[i]) 54 if(dis[to[i]]>dis[a]+val[i]) {dis[to[i]]=dis[a]+val[i];if(!vis[to[i]])q.push((node){to[i],dis[to[i]]});}; 55 } 56 return dis[id[t]]; 57 } 58 int main() 59 { 60 freopen("trip.in","r",stdin); 61 freopen("trip.out","w",stdout); 62 n=read(),s=read(),t=read(); 63 for(int i=1;i<=n;i++) x[i]=read(); 64 for(int i=1;i<=n;i++) w[i]=read(); 65 for(int i=1;i<=n;i++) v[i]=read(); 66 build(1,1,n);int l,r; 67 for(int i=1;i<=n;i++) 68 { 69 l=max(1LL,lower_bound(x+1,x+n+1,x[i]-w[i])-x),r=upper_bound(x+1,x+n+1,x[i]+w[i])-x-1; 70 mdf(1,1,n,l,r,i); 71 } 72 printf("%lld",dij()); 73 }