高精度数加法 (100 分)
题目
高精度数是指大大超出了标准数据类型能表示的范围的数,例如10000位整数。很多计算问题的结果都很大,因此,高精度数极其重要。
一般使用一个数组来存储高精度数的所有数位,数组中的每个元素存储该高精度数的1位数字或多位数字。 请尝试计算:N个高精度数的加和。这个任务对于在学习数据结构的你来说应该是小菜一碟。 。
输入格式:
第1行,1个整数N,表示高精度整数的个数,(1≤N≤10000)。
第2至N+1行,每行1个高精度整数x, x最多100位。
输出格式:
1行,1个高精度整数,表示输入的N个高精度数的加和。
输入样例:
在这里给出一组输入。例如:
3
12345678910
12345678910
12345678910
输出样例:
在这里给出相应的输出。例如:
37037036730
思路
大数加法,用进位将加后的数存到数组中,注意此题不只是两个加数,而可能是多个加数即可。
代码
#include<bits/stdc++.h>
using namespace std;
int SQuc[10001];
int num[101]={0};
char s[101];
int main(){
int u;
int length1;
int length2;
scanf("%d\n",&u);
scanf("%s",s);
length1=strlen(s);
int j=1;
for(int i=length1-1;i>=0;i--){
SQuc[j]=s[i]-'0';
j++;
}
int ant=0,ent;
for(int k=2;k<=u;k++)
{
char temp[101];
scanf("%s",temp);
length2=strlen(temp);
for(int y=0;y<101;y++){
num[y]=0;
}
for(int o=length2-1,j=1;o>=0;o--,j++){
num[j]=temp[o]-'0';
}
if(length1<length2){
length1=length2;
}
ant=0;
for(int i=1;i<=length1;i++){
ent=num[i]+SQuc[i]+ant;
if(ent>9){
ant=ent/10;
SQuc[i]=ent%10;
}
else
{
ant=0;
SQuc[i]=ent;
}
}
if(ant!=0){
length1++;
SQuc[length1]=ant%10;
}
}
for(int i=length1;i>=1;i--){
printf("%d",SQuc[i]);
}
return 0;
}
二叉树加权距离 (100 分)
题目
二叉树结点间的一种加权距离定义为:上行方向的变数×3 +下行方向的边数×2 。上行方向是指由结点向根的方向,下行方向是指与由根向叶结点方向。 给定一棵二叉树T及两个结点u和v,试求u到v的加权距离。
输入格式:
第1行,1个整数N,表示二叉树的结点数,(1≤N≤100000)。
随后若干行,每行两个整数a和b,用空格分隔,表示结点a到结点b有一条边,a、b是结点的编号,1≤a、b≤N;根结点编号为1,边从根向叶结点方向。
最后1行,两个整数u和v,用空格分隔,表示所查询的两个结点的编号,1≤u、v≤N。
输出格式:
1行,1个整数,表示查询的加权距离。
输入样例:
在这里给出一组输入。例如:
5
1 2
2 3
1 4
4 5
3 4
输出样例:
在这里给出相应的输出。例如:
8
思路
这道题我用了图论解法,上行边权值赋值为3,下行边权值赋值为2,在转化为求最短路问题跑一遍spfa即可。
代码
#include<bits/stdc++.h>
#define MAX 300001
#define maxa 1000001
using namespace std;
int n;
int dis[MAX],head[MAX];
int tot;
int vis[MAX];
queue<int> q;
struct edge{
int nxt,to,w;
}e[MAX];
void Csh(int s){
for(int i=1;i<=n;i++){
dis[i]=maxa;
vis[i]=0;
}
dis[s]=0;
q.push(s);
}
void add(int u,int v,int w=0){
e[++tot].to=v;
e[tot].nxt=head[u];
e[tot].w=w;
head[u]=tot;
}
void Spfa(int s){
while(!q.empty()){
int u=q.front();
q.pop();
vis[u]=false;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(dis[v]>dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
if(!vis[v]){
vis[v]=1;
q.push(v);
}
}
}
}
}
int main(){
cin>>n;
for(int i=1;i<n;i++){
int u,v;
cin>>u>>v;
add(u,v,2);
add(v,u,3);
}
int start;
int end1;
cin>>start>>end1;
Csh(start);
Spfa(start);
cout<<dis[end1];
return 0;
}
修轻轨 (100 分)
题目
长春市有n个交通枢纽,计划在1号枢纽到n号枢纽之间修建一条轻轨。轻轨由多段隧道组成,候选隧道有m段。每段候选隧道只能由一个公司施工,施工天数对各家公司一致。有n家施工公司,每家公司同时最多只能修建一条候选隧道。所有公司可以同时开始施工。请评估:修建这条轻轨最少要多少天。。
输入格式:
第1行,两个整数n和m,用空格分隔,分别表示交通枢纽的数量和候选隧道的数量,1 ≤ n ≤ 100000,1 ≤ m ≤ 200000。
第2行到第m+1行,每行三个整数a、b、c,用空格分隔,表示枢纽a和枢纽b之间可以修建一条双向隧道,施工时间为c天,1 ≤ a, b ≤ n,1 ≤ c ≤ 1000000。
输出格式:
输出一行,包含一个整数,表示最少施工天数。
输入样例:
在这里给出一组输入。例如:
6 6
1 2 4
2 3 4
3 6 7
1 4 2
4 5 5
5 6 6
输出样例:
在这里给出相应的输出。例如:
6
思路
一开始没读懂题目。
这道题应该是一道求最小生成树的问题,但是结束条件改为第一个点和第n个点相连即可结束,所以我使用了克鲁斯卡尔算法,用并查集约束结束条件。
代码
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define MAXN 200000 //顶点个数的最大值
#define MAXM 200000 //边的个数的最大值
using namespace std;
struct edge //边
{
int u, v, w; //边的顶点、权值
}edges[MAXM]; //边的数组
int a[MAXM];
int n, m; //顶点个数、边的个数
int i, j; //循环变量
int Find(int x)
{
return a[x] == x ? x : a[x] = Find(a[x]);
}
void Union(int aa, int bb)
{
int x = Find(aa), y = Find(bb);
if (x != y)
{
a[x] = y;
}
}
bool cmp( edge a, edge b ) //实现从小到大排序的比较函数
{
return a.w <b.w;
}
int main( )
{
int u, v, w; //边的起点和终点及权值
scanf( "%d%d", &n, &m ); //读入顶点个数 n
for( int i=0; i<m; i++ )
{
scanf( "%d%d%d", &u, &v, &w ); //读入边的起点和终点
edges[i].u = u; edges[i].v = v; edges[i].w = w;
}
for (int i = 1; i <= n; ++i)a[i] = i;
sort(edges,edges+m,cmp);
long long ans = 0;
int cnt=0;
for (int i = 0; i < m; ++i)
{
if (Find(edges[i].u) != Find(edges[i].v))
{
ans = edges[i].w;
Union(edges[i].u, edges[i].v);
}
if (Find(1) ==Find(n))break;
}
printf("%lld\n", ans);
}
数据结构设计(100 分)
题目
小唐正在学习数据结构。他尝试应用数据结构理论处理数据。最近,他接到一个任务,要求维护一个动态数据表,并支持如下操作:
插入操作(I):从表的一端插入一个整数。
删除操作(D):从表的另一端删除一个整数。
取反操作(R):把当前表中的所有整数都变成相反数。
取最大值操作(M):取当前表中的最大值。
如何高效实现这个动态数据结构呢?
输入格式:
第1行,包含1个整数M,代表操作的个数, 2≤M≤1000000。
第2到M+1行,每行包含1个操作。每个操作以一个字符开头,可以是I、D、R、M。如果是I操作,格式如下:I x, x代表插入的整数,-10000000≤x≤10000000。 。
输出格式:
若干行,每行1个整数,对应M操作的返回值。如果M和D操作时队列为空,忽略对应操作。
输入样例:
在这里给出一组输入。例如:
6
I 6
R
I 2
M
D
M
输出样例:
在这里给出相应的输出。例如:
2
2
思路
AC代码。
代码
#include<bits/stdc++.h>
using namespace std;
const int max1 = 1000002;
int cel;
deque<int> ri, le;
int lazy;
int a[max1];
int cnt;
int del;
int main()
{
scanf("%d",&cel);
char oper[2];
for (int i = 1; i <= cel; ++i)
{
scanf("%s",oper);
if (oper[0] == 'I')
{
cnt+=1;
scanf("%d", &a[cnt]);
if (lazy)
a[cnt] = -a[cnt];
int tmp = a[cnt];
while (!ri.empty() && a[ri.back()] >= tmp)
ri.pop_back();
ri.push_back(cnt);
while (!le.empty() && a[le.back()] <= tmp)
le.pop_back();
le.push_back(cnt);
}
if (oper[0] == 'R')
{
lazy^= 1;
}
if (oper[0]== 'D')
{
if (del < cnt) {
del++;
while (!ri.empty() && ri.front() <= del)
ri.pop_front();
while (!le.empty() && le.front() <= del)
le.pop_front();
}
}
if (oper[0] == 'M')
{
if (del < cnt) {
if (lazy)
{
printf("%d\n", -a[ri.front()]);
}
else
{
printf("%d\n", a[le.front()]);
}
}
}
}
}
思路
超时代码(70分),可能是遍历的时间过长,但是思路很清晰。
代码
#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
deque<int>dq;
int x;
int m;
char s;
void func(char s)
{
if(s=='I')
{ cin>>x;
dq.push_front(x);
}
else if(s=='D'&&dq.empty()!=1)
{
dq.pop_back();
}
else if(s=='R')
{
for(deque<int>::iterator it=dq.begin();it!=dq.end();++it)
*it=(-1)*(*it);
}
else if(s=='M'&&dq.empty()!=1)
{
int q=-99999999999;
for(deque<int>::iterator it=dq.begin();it!=dq.end();++it){
if(*it>=q)
q=*it;
}
cout<<q<<endl;
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cin>>m;
for(int i=1;i<=m;i++)
{
cin>>s;
func(s);
}
}