zoukankan      html  css  js  c++  java
  • 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^12T<=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
    ",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
    ",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"
    ",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 }
    60分
     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 }
    std
  • 相关阅读:
    一条代码快速解决滚动条隐藏问题
    微信小程序:wx:for循环输出的使用方法以及简单例子
    点运算符(.)和中括号运算符([])有哪些区别
    线程
    ArrayMap 和HashMap的区别
    Android加载图片的策略
    Android图片加载为什么选择glide
    Android 设计模式对比
    Android 注解框架对比
    ReactNative编写规范
  • 原文地址:https://www.cnblogs.com/drizzly/p/7779971.html
Copyright © 2011-2022 走看看