【42模拟测试题】【归并排序】【树规】【贪心】

题目:



强迫症
问题描述
人行道铺着两行地砖,第一行每块的长度是A/B,第二行每块的长度是X/Y。两行砖块第一块的一边是对齐的。

作为一个强迫症患者,看到这样的地砖你很不爽,于是就想知道,最少隔多少距离后两行地砖的缝隙又会对齐。
输入格式
输入第一行包含一个整数T,表示测试点组数。
接下来T行,每行两个分数,格式为A/B X/Y,两个分数中间用一个空格隔开。
输出格式
T行,每行包含一个分数(若答案为整数则输出整数),表示每组数据的答案。分数必须以最简形式输出。
样例输入
2
3/2 5/8
4/3 3/10
样例输出
15/2
12
数据范围
30%的数据A,B,X,Y<=20
70%的数据T<=10
100%的数据1<=A,B,X,Y,<=10,000,T<=100,000



手套
问题描述
你现在有N对手套,但是你不小心把它们弄乱了,需要把它们整理一下。N对手套被一字排开,每只手套都有一个颜色,被记为0~N-1,你打算通过交换把每对手套都排在一起。由于手套比较多,你每次只能交换相邻两个手套。请你计算最少要交换几次才能把手套排整齐。
输入格式
输入第一行一个N,表示手套对数。
第二行有2N个整数,描述了手套的颜色。每个数都在0~N-1之间,且每个数字都会出现恰好两次。
输出格式
一行,包含一个数,表示最少交换次数。
样例输入
2
0 1 0 1
样例输出
1
数据范围
30%的数据N≤9;
60%的数据N≤1000;
100%的数据N≤200,000。



星座
问题描述
星空中有n颗星星,有n-1对星星间被人为地连上了线,每条连线有各自的长度。所有星星被连成了一个整体。现在,你要在星系中找到一个最大的十字形星座。即,你要找到两条星星构成的路径,使得它们恰好有一颗公共星(这颗公共星不能是某条路径的端点),且两条路径的长度和最大。
左图红线表示了一个合法的十字形星座,而右图的星座并不合法。

输入格式
第一行一个数n,表示星星的数量。
接下来n行,每行3个数x,y,z,表示第x颗星星和第y颗星星间有一条连线,它的长度是z。
输出格式
一行,包含一个整数,表示最大的路径长度和。若答案不存在,输出-1。
样例输入
10
3 8 6
9 3 5
1 9 2
4 8 6
2 3 3
10 4 8
5 9 5
7 2 3
6 9 1
样例输出
33
数据范围
20%的数据n<=1000
50%的数据n<=10,000
100%的数据n<=100,000,0<=z<=1000



解题报告:

  这又是一个星期前的考试了,还记得这是我考的名次最好的一次,第四名。本来该得220的,结果第一题忘开long long了,就丢了70分。。。

  第一题,水题,找最小公倍数就可以了。但是,但是最小公倍数有可能超过int,所以必须开long long。一定要注意数据范围,失分惨重。

 1 #include<iostream>
 2 #include<cstdio>
 3 #define ll long long
 4 using namespace std;
 5 ll t;
 6 ll gcd(ll a,ll b)
 7 {
 8     return b==0?a:gcd(b,a%b);
 9 }
10 ll lcm(ll a,ll b)
11 {
12     return a*b/gcd(a,b);
13 }
14 int main()
15 {
16     freopen("tile.in","r",stdin);
17     freopen("tile.out","w",stdout);
18     cin>>t;
19     while (t)
20     {
21         ll a,b,x,y;
22         scanf("%I64d/%I64d%I64d/%I64d",&a,&b,&x,&y);
23         ll p1=lcm(b,y);
24         a*=(p1/b);x*=(p1/y);
25         ll p2=lcm(a,x);
26         ll o=gcd(p1,p2);
27         p1/=o;p2/=o;
28         if (p1==1) printf("%I64d\n",p2);
29         else printf("%I64d/%I64d\n",p2,p1);
30         t--;
31     }
32     return 0;
33 }

  第二题,贪心的思想可以过70 (T了3组),就是从第一个数开始,把另一个移到它右边,花费它们之间的距离的步数,是不会影响中间的数的排列顺序的,然后扫描下一个,直到每一种数字都扫描完。正解:把数组按出现顺序重新赋值组成一个数组,如:2 0 1 3 3 1 2 0 的手套,可以组成:1 (2第一次出现,tot++) 2 3 4 4(3第二次出现,第一次出现3的编号为4) 3 1 2  ,然后求这个数组的逆序对即可。

 这里要注意,对归并排序的复习。还有,要开long long。!!

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define ll long long
 5 using namespace std;
 6 const ll maxn=400005;
 7 ll num[maxn],a[maxn];
 8 ll b[maxn],r[maxn];
 9 ll n,ans,tot,t;
10 void mergesort (ll s,ll t)
11 {
12     if (s==t) return ;
13     ll mid=(s+t)/2;
14     mergesort(s,mid);
15     mergesort(mid+1,t);
16     ll i=s,j=mid+1,k=s;
17     while (i<=mid&&j<=t)
18     {
19         if (a[i]<=a[j])
20             r[k++]=a[i++];
21         else {
22             r[k++]=a[j++];
23             ans+=mid-i+1;
24         }
25     }
26     while (i<=mid)
27       r[k++]=a[i++];
28     while (j<=t)
29       r[k++]=a[j++];
30     for (int i=s;i<=t;i++)
31       a[i]=r[i];
32 }
33 int main()
34 {
35     freopen("gloves.in","r",stdin);
36     freopen("gloves.out","w",stdout);
37     cin>>n;
38     n*=2;
39     for (ll i=1;i<=n;i++)
40     {
41         scanf("%I64d",&num[i]);
42         if (!b[num[i]]){
43             a[i]=++tot;
44             b[num[i]]=a[i];
45         }
46         else a[i]=b[num[i]];
47     }
48     mergesort(1,n);
49     printf("%I64d",ans);
50     return 0;
51 }

  第三题,考试的时候用优化过的暴力过了50,(T了5组),主要就是建无向图,然后找度大于等于4的点,从这个点找4条最长的road,然后相加与ans比较,最后得到答案。正解:树形规划,对于一个点,可以有两种选法,选它的儿子中最长的四条边或者选它的父亲的一条最长边和自己儿子的三条边(注意:在选父亲的最长边时不能是自己现在的这条边)从叶子节点一直向上推即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 const int maxn=100005;
 5 int n,ans;
 6 int to[maxn*2],ne[maxn*2],w[maxn*2],he[maxn],tot;
 7 int du[maxn],f[maxn][5],fa[maxn],s[maxn];
 8 void add(int a,int b,int c)
 9 {
10     tot++;to[tot]=b;ne[tot]=he[a];w[tot]=c;he[a]=tot;
11     //tot++;to[tot]=a;ne[tot]=he[b];w[tot]=c;he[b]=tot;
12 }
13 void comp(int x,int &a,int &b,int &c,int &d)//找最长的四条边
14 {
15     if (x<=d) return ;
16     if (x>c) d=c;
17     else {
18         d=x;return ;
19     }
20     if (x>b) c=b;
21     else {
22         c=x;return ;
23     }
24     if (x>a) {
25         b=a;
26         a=x;
27         return ;
28     }
29     b=x;
30     return;
31 }
32 inline int dfs(int x,int dis)//inline 函数
33 {
34     int u;bool flag=false;
35     for (int i=he[x];i;i=ne[i])
36     if (to[i]!=fa[x]){
37         fa[to[i]]=x;//当前节点的父亲
38         s[to[i]]=w[i];//儿子到父亲的距离
39         flag=true;
40         u=dfs(to[i],dis+w[i]);//dis是一直向下加的
41         u-=dis;//减去现在加到的长度,就是之间的距离
42         comp(u,f[x][0],f[x][1],f[x][2],f[x][3]);
43     }
44      if (!flag) return dis;//到叶子节点就返回这段距离
45     return dis+f[x][0];
46 }
47 int main()
48 {
49     freopen("cross.in","r",stdin);
50     freopen("cross.out","w",stdout);
51     cin>>n;
52     for (int i=1;i<n;i++)
53     {
54         int a,b,c;
55         scanf("%d%d%d",&a,&b,&c);
56         du[a]++;du[b]++;
57         add(a,b,c);
58         add(b,a,c);
59     }
60     dfs(1,0);
61     for (int i=1;i<=n;i++)
62       if (du[i]>=4)
63       {
64            if (f[i][3]) ans=max(ans,f[i][0]+f[i][1]+f[i][2]+f[i][3]); //能从儿子中选出来
65            int j=i,fat=fa[j],di=0;
66            while (j!=1)//向父亲,父亲的父亲,父亲的父亲的父亲(祖先)找一条最长边
67            {
68                int t=f[fat][0];//这个祖先的最长边
69             di+=s[j];    //加上得到当前 i 到这个 祖先的距离
70                if (f[fat][0]==f[j][0]+s[j])//s[j]  !!not di
71                   t=f[fat][1];
72                ans=max(ans,t+f[i][0]+f[i][1]+f[i][2]+di);//祖先向下的最长边加上i到这个祖先的距离
73                j=fa[j];//下一个
74                fat=fa[fat];//下一个祖先
75            }
76       }
77     cout<<ans;
78     return 0;
79 }

  加油!不要“唱歌”咯。

时间: 2024-12-08 23:54:28

【42模拟测试题】【归并排序】【树规】【贪心】的相关文章

bzoj1124[POI2008]枪战maf tarjan+树规+贪心/线性DP

这代码快写死我了.....死人最多随便推推结论.死人最少,每个环可以单独考虑,每个环上挂着的每棵树也可以分别考虑.tarjan找出所有环,对环上每个点,求出选它和不选它时以它为根的树的最大独立集(就是最多活下来的人数),然后环上每个点选或不选对应的是一个“价值”,这个价值是那个点挂着的树里最多存活人数.先全都不选环上的点,算出选和不选时最大独立集的差值,问题变成有一个环,环上有一堆数(那些差值),选出一些不相邻的数使得和最大,然后我按着bzoj2151种树写了个贪心....这个贪心的思路也很神,

CodeForces 706D Vasiliy&#39;s Multiset (字典树查询+贪心)

题意:最开始的时候有一个集合,集合里面只有一个元素0,现在有q次操作,操作分为3种: + x: 表示向集合中添加一个元素x - x:表示删除集合中值为x的一个元素 ? x:表示查询集合中与x异或的最大值为多少 析:这是一个字典树的应用,不过确实没看出来....主要思想是这样,先用10进制数,转成二进制数,记下每个结点的0,1的个数,这样增加和删除,就是对01的删除, 剩下的就是查询,那么尽量让0和1XOR是最大的,所以,对于给定数,我们要去尽量他的XOR数,如果找到就加上,找不到,就找下一个.这

笔试算法题(42):线段树(区间树,Interval Tree)

议题:线段树(Interval Tree) 分析: 线段树是一种二叉搜索树,将一个大区间划分成单元区间,每个单元区间对应一个叶子节点:内部节点对应部分区间,如对于一个内部节点[a, b]而言,其左子节点表示的区间为[a, (a+b)/2],其右子节点表示的区间为[1+(a+b)/2, b]: 对于区间长度为N的线段树,由于其单元节点都是[a, a]的叶子节点,所以其叶子节点数为N,并且整棵树为平衡二叉树,所以总节点数为2N-1,树的深度为log(N)+1: 插入操作:将一条线段[a, b]插入到

POJ 3253 Fence Repair 类似哈夫曼树的贪心思想

Fence Repair Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 24550   Accepted: 7878 Description Farmer John wants to repair a small length of the fence around the pasture. He measures the fence and finds that he needs N (1 ≤ N ≤ 20,000)

UVA 11990 `Dynamic&#39;&#39; Inversion CDQ分治, 归并排序, 树状数组, 尺取法, 三偏序统计 难度: 2

题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3141 题意 一个1到n的排列,每次随机删除一个,问删除前的逆序数 思路 综合考虑,对每个数点,令value为值,pos为位置,time为出现时间(总时间-消失时间),明显是统计value1 > value2, pos1 < pos2, time1 < time2的个

【2018.12.15】【考试总结】【模拟+逆序对+树状数组+贪心+multiset】爆零之旅

这是我悲惨的接近爆零的一次考试,但是本蒟蒻不能放弃,还是要总结的QAQ 答题卡 [题目背景] 八月是个悲惨的月份.先不谈炎热的天气,对于新生来说,八月意味着军训: 而对于高二高三的同学来说,八月意味着开学考试.而考试就意味着改卷,改卷 也就意味着答题卡.不幸的是,学校读答题卡的机器的评分软件坏了,wyx 就被 老师要求写一个评分的程序. [问题描述] 软件需要读入学生的姓名.试题答案以及学生的答题卡信息. 学生姓名 学校的信息管理系统中存储了所有学生的姓名,一共 名学生.每个学生的 名字的组成只

代码与算法集锦-归并排序+树状数组+快排+深度优先搜索+01背包(动态规划)

归并排序 求逆序数 归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用. 首先考虑下如何将将二个有序数列合并.这个非常简单,只要从比较二个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数.然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可. //将有序数组a[]和b[]合并到c[]中 void MemeryArray(int a[], int n, int b[], int m, int c

python简单模拟:把树存储在数据表中

在数据库中建立一个表,有Id, fatherId, value 三个字段,就可以存储一个树. 如何把该表中的数据以树的形式呈现出来,下面小弟用python简单模拟一下. 初学python,请大家多多指点.另外非常感谢http://www.cnblogs.com/lzyzizi/对小弟的指点. 运行结果: A-1 B-1 C-1 D-1 E-1 E-2 C-2 B-2 C-3 C-4 源代码: 1 #!user/bin/python 2   3  class noteModel: 4 def __

hdu 5338 线段树+stl+贪心

下午比赛的时候写搓了,晚上重写一次就过了,o(╯□╰)o. 思路:按照字典序贪心,用线段树来维护区间最值,用set来维护求出答案的封闭区间. 1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 #include <cmath> 6 #include <set> 7 using namespace std; 8 9