11.3 AHSOFNU 校内模拟
Posted drizzly
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了11.3 AHSOFNU 校内模拟相关的知识,希望对你有一定的参考价值。
块(block)
【问题描述】
拼图达人小 C 手里有 n 个 1*1 的正方形方块,他希望把这些方块拼在一起, 使得拼出的图形周长最小, 要求方块不能重叠。 擅长拼图的小 C 一下就求出了这个周长, 顺便他想考考你会不会求。
【输入格式】
多组数据, 第一行一个正整数 T, 表示数据组数。
接下来 T 行, 每行一个正整数 n, 表示方块数。
【输出格式】
输出 T 行, 每行一个正整数, 表示答案。
【样例输入】
3
4
11
22
【样例输出】
8
14
20
【数据范围】
对于 20%的数据, n<=20;
对于 40%的数据, n<=1000;
对于 60%的数据, n<=10^6;
对于 80%的数据, n<=10^10;
对于 100%的数据, n<=10^12, T<=10。
Solution:
数学题。首先正方形一定是周长最小的,由此可以对 n 进行开方,然后把剩下的小方块围在正方形边上即可。
Code:
1 #include<cstdio> 2 #define MAXN 1000000 3 #define ll long long 4 #define debug 0 5 using namespace std; 6 int t,ans=0; 7 inline int Sqrt(ll x){ 8 ll l=0,r=MAXN; 9 while(l<=r){ 10 ll mid=(l+r)>>1; 11 if(mid*mid<=x&&(mid+1)*(mid+1)>x) return mid; 12 if (mid*mid<x) l=mid+1; 13 else r=mid-1; 14 } 15 } 16 int main(){ 17 freopen("block.in","r",stdin); 18 freopen("block.out","w",stdout); 19 scanf("%d",&t); 20 for(int i=1;i<=t;i++){ 21 ll n;scanf("%lld",&n); 22 int len=Sqrt(n); 23 #if debug 24 printf("len=%d\n",len); 25 #endif 26 ans=4*len; 27 n-=1ll*len*len; 28 if(n<=len&&n>=1) ans+=2; 29 else if(n>len) ans+=4; 30 printf("%d\n",ans); 31 } 32 return 0; 33 }
树(tree)
【问题描述】
今天 F 大爷看到了一张 n 个点的无向完全图, 每条边有边权。 F大爷一开心就花 0.03 飞秒(即3*10-17 秒) 求了一下这张图的最小生成树以及最小生成树的个数。 F 大爷惊喜地发现这张图只有一个最小生成树, 他现在更开心了, 于是他把这个最小生成树告诉了你, 要你求出原来的完全图中边权和最小是多少。
【输入格式】
多组数据, 第一行一个正整数 T, 表示数据组数。
每组数据的第一行一个正整数 n, 表示点数。
接下来 n-1 行, 每行三个正整数 xi,yi,wi, 表示最小生成树上 xi和 yi 之间有一条权值为 wi 的边。
【输出格式】
输出 T 行, 每行一个整数, 表示答案。
【样例输入】
2
3
1 2 4
2 3 7
4
1 2 1
1 3 1
1 4 2
【样例输出】
19
12
【数据范围】
对于 20%的数据, T,n,wi<=5;
对于另外 30%的数据, n<=1000, 给的树是一条链;
对于 100%的数据, T<=10, n<=20000, wi<=10000。
Solution:
并查集。
考虑kruskal,每次连上一条边,两个端点所在的联通块之间连的边除了我们要加入的边,其他边都必须大于这条边,带权并查集维护即可。
Code:
1 #include<cstdio> 2 #include<algorithm> 3 #define MAXN 20005 4 #define ll long long 5 #ifdef WIN32 6 #define LL "%I64d" 7 #else 8 #define LL "%lld" 9 #endif 10 using namespace std; 11 int t,n; 12 ll ans=0; 13 struct edge{ 14 int u,v,val; 15 }e[MAXN]; 16 int fa[MAXN],val[MAXN],size[MAXN]; 17 inline int cmp(edge a,edge b){return a.val<b.val;} 18 inline int find(int x){ 19 if(fa[x]==x) return x; 20 return fa[x]=find(fa[x]); 21 } 22 inline int merge(int x,int y,int val){ 23 int fx=find(x),fy=find(y); 24 ans+=1LL*size[fx]*size[fy]*(val+1)-1; 25 fa[fx]=fy;size[fy]+=size[fx]; 26 } 27 int main(){ 28 freopen("tree.in","r",stdin); 29 freopen("tree.out","w",stdout); 30 scanf("%d",&t); 31 for(int i=1;i<=t;i++){ 32 ans=0; 33 scanf("%d",&n); 34 for(int i=1;i<=n;i++) fa[i]=i,size[i]=1; 35 for(int j=1;j<=n-1;j++){ 36 scanf("%d%d%d",&e[j].u,&e[j].v,&e[j].val); 37 } 38 sort(e+1,e+n,cmp); 39 for(int j=1;j<=n-1;j++){ 40 merge(e[j].u,e[j].v,e[j].val); 41 } 42 printf(LL"\n",ans); 43 } 44 }
球(ball)
【问题描述】
有 n 个不同颜色的球排成一排, 其中 n 为偶数。 小 D 打算把这些球按照某种玄妙的顺序放入一个球筒中。每次他会选择一个不是当前第一个的球, 先把这个球放入球筒, 接着把这个球的前一个也放入球筒, 重复这个操作直到所有球都进入球筒。 小 D 希望最后球筒中从顶到底的颜色序列字典序最小, 但他不会做, 所以请你帮帮他。
【输入格式】
第一行一个正整数 n, 表示球的个数。
第二行 n 个正整数 ai, 分别表示每个球的颜色。
【输出格式】
输出一行 n 个正整数, 表示球筒字典序最小的颜色序列。
【样例输入 1】
4
3 2 4 1
【样例输出 1】
3 1 2 4
【样例输入 2】
8
4 6 3 2 8 5 7 1
【样例输出 2】
3 1 2 7 4 6 8 5
【数据范围】
对于 30%的数据, n<=10;
对于 60%的数据, n<=1000;
对于 100%的数据, n<=200000, 1<=ai<=n, ai 互不相同。
Solution:
60分做法:直接暴力。
100分做法:倒着考虑取的顺序,每次相当于把当前区间分成三段,每段长度都为偶数,支持分奇偶RMQ即可,再用堆维护这些区间,就能AC。(并不会...)
1 #include<cstdio> 2 #include<cstring> 3 #define MAXN 200005 4 #define INF 0x7fffffff 5 using namespace std; 6 int n,ans=0; 7 int a[MAXN],vis[MAXN]; 8 bool flag; 9 int main(){ 10 freopen("ball.in","r",stdin); 11 freopen("ball.out","w",stdout); 12 memset(vis,0,sizeof(vis)); 13 scanf("%d",&n);a[0]=INF; 14 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 15 for(int i=1;i<=n/2;i++){ 16 int cnt1=0,cnt2=0;flag=0; 17 for(int j=1;j<=n;j++){ 18 if(vis[j]==0){ 19 flag=flag?0:1;if(a[j]<a[cnt1]&&flag) cnt1=j; 20 } 21 } 22 vis[cnt1]=1;flag=0; 23 for(int j=cnt1+1;j<=n;j++){ 24 if(vis[j]==0){ 25 flag=flag?0:1;if(a[j]<a[cnt2]&&flag) cnt2=j; 26 } 27 else break; 28 } 29 vis[cnt2]=1;flag=0; 30 printf("%d %d ",a[cnt1],a[cnt2]); 31 } 32 }
1 #include<cstdio> 2 #include<queue> 3 using namespace std; 4 #define N 262144 5 #define INF 0x3FFFFFFF 6 #define mp make_pair 7 #define tp pq.top() 8 #define F first 9 #define S second 10 int t1[N*2+5],t2[N*2+5],p[N]; 11 priority_queue<pair<pair<int,int>,pair<int,int> > > pq; 12 void build(int*t){for(int i=N;--i;)t[i]=min(t[i<<1],t[i<<1|1]);} 13 int query(int*t,int l,int r) 14 { 15 int res=INF; 16 for(l+=N-1,r+=N+1;l^r^1;l>>=1,r>>=1) 17 { 18 if(~l&1)res=min(res,t[l+1]); 19 if( r&1)res=min(res,t[r-1]); 20 } 21 return res; 22 } 23 void push(int l,int r) 24 { 25 if(l>r)return; 26 int x=query(l&1?t1:t2,l,r); 27 pq.push(mp(mp(-x,query(l&1?t2:t1,p[x]+1,r)),mp(l,r))); 28 } 29 int main() 30 { 31 freopen("ball.in","r",stdin); 32 freopen("ball.out","w",stdout); 33 int n,i,x,y,l,r; 34 scanf("%d",&n); 35 for(i=1;i<=n;++i)scanf("%d",&x),p[x]=i,t1[i+N]=i&1?x:INF,t2[i+N]=i&1?INF:x; 36 build(t1);build(t2); 37 for(push(1,n);!pq.empty();) 38 { 39 x=-tp.F.F;y=tp.F.S;l=tp.S.F;r=tp.S.S; 40 printf("%d %d ",x,y);pq.pop(); 41 push(l,p[x]-1);push(p[x]+1,p[y]-1);push(p[y]+1,r); 42 } 43 fclose(stdin);fclose(stdout);return 0; 44 }
以上是关于11.3 AHSOFNU 校内模拟的主要内容,如果未能解决你的问题,请参考以下文章