数列查询 (100 分)
题目
已知数列的通项公式为:
f(n) = f(n-1)*11/10,f[1]=10.
通项从左向右计算,*和/分别表示整数乘法和除法。 现在,要多次查询数列项的值。
输入格式:
第1行,1个整数q,表示查询的次数, 1≤q≤10000. 第2至q+1行,每行1个整数i,表示要查询f(i)的值。
输出格式:
q行,每行1个整数,表示f(i)的值。查询的值都在32位整数范围内。
输入样例:
在这里给出一组输入。例如:
3
1
2
3
输出样例:
在这里给出相应的输出。例如:
10
11
12
思路
第一题,我使用了打表的做法,即先把题目所需长度的函数值存在数组中,当下面输入指定数字时,即可输出函数值,节省了时间。
注意!:
不能用endl,cin,cout,要用‘\n’,scanf,printf来替换。
代码
#include<iostream>
#define endl "\n"
using namespace std;
int main(){
int a[10000];
a[0]=10;
int i;
int q;
ios::sync_with_stdio(false);
cin.tie(0);
cin>>q;
for(i=1;i<=200;i++){
a[i]=a[i-1]*11/10;
}
int temp;
for(i=0;i<q;i++){
cin>>temp;
cout<<a[temp-1]<<"\n";
}
return 0;
}
稀疏矩阵之和 (100 分)
题目
矩阵A和B都是稀疏矩阵。请计算矩阵的和A+B.如果A、B不能做和,输出“Illegal!”
输入格式:
矩阵的输入采用三元组表示,先A后B。对每个矩阵:
第1行,3个整数N、M、t,用空格分隔,分别表示矩阵的行数、列数和非0数据项数,10≤N、M≤50000,t≤min(N,M).
第2至t+1行,每行3个整数r、c、v,用空格分隔,表示矩阵r行c列的位置是非0数据项v, v在32位有符号整型范围内。三元组默认按行列排序。
输出格式:
矩阵A+B,采用三元组表示,默认按行列排序,非零项也在32位有符号整型范围内。
输入样例:
10 10 3
2 2 2
5 5 5
10 10 20
10 10 2
2 2 1
6 6 6
输出样例:
10 10 4
2 2 3
5 5 5
6 6 6
10 10 20
思路
第二题,我使用了两个结构体来存储三元组,并且要注意排序的方式,我使用了sort排序并且自定义cmp函数的方式完成了排序,之后就是列举所有可能发生的情况,并且最终得出结果。
注意!:
1.要注意如果两个矩阵中有和为0的情况,要在生成的矩阵中把那一项去掉。
2.注意排序的方式,先行后列。
3.注意输出不合法的情况。
代码
#include<iostream>
#include<algorithm>
#define endl "\n"
using namespace std;
int maxn=99999;
struct syz{
int row;
int col;
int d;
};
struct all{
int r;
int c;
int num;
syz n[50001];
};
bool cmp(syz a,syz b){
if(a.row!=b.row) return a.row<b.row;
else return a.col<b.col;
}
bool init(all &m){
int r,c,numq;
cin>>r>>c>>numq;
m.r=r;
m.c=c;
m.num=0;
while(numq){
int x1,x2,x3;
cin>>x1>>x2>>x3;
if(x1>m.r||x1<=0||x2>m.c||x2<=0){
return 0;
}
m.n[m.num].row=x1;
m.n[m.num].col=x2;
m.n[m.num].d=x3;
m.num++;
numq--;
}
sort(m.n,m.n+m.num,cmp);
return 1;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
all m;
all n;
all temp;
if(!init(m)){
cout<<"Illegal!";
return 0;
}
if(!init(n)){
cout<<"Illegal!";
return 0;
}
int temp1=0,temp2=0,temp3=0;
if(m.r!=n.r||m.c!=n.c){
cout<<"Illegal!"<<endl;
return 0;
}
temp.r=m.r;
temp.c=m.c;
while(temp1<m.num||temp2<n.num){
if(temp1<m.num&&temp2<n.num&&m.n[temp1].row<n.n[temp2].row){
temp.n[temp3].row=m.n[temp1].row;
temp.n[temp3].col=m.n[temp1].col;
temp.n[temp3].d=m.n[temp1].d;
temp1++;
temp3++;
}
else if(temp1<m.num&&temp2<n.num&&m.n[temp1].row==n.n[temp2].row){
if(m.n[temp1].col<n.n[temp2].col){
temp.n[temp3].row=m.n[temp1].row;
temp.n[temp3].col=m.n[temp1].col;
temp.n[temp3].d=m.n[temp1].d;
temp1++;
temp3++;
}
else if(temp1<m.num&&temp2<n.num&&m.n[temp1].col==n.n[temp2].col){
int q=temp.n[temp3].d=m.n[temp1].d+n.n[temp2].d;
if(q){
temp.n[temp3].row=m.n[temp1].row;
temp.n[temp3].col=m.n[temp1].col;
temp.n[temp3].d=m.n[temp1].d+n.n[temp2].d;
temp3++;
}
temp1++;
temp2++;
}
else if(temp1<m.num&&temp2<n.num){
temp.n[temp3].row=n.n[temp2].row;
temp.n[temp3].col=n.n[temp2].col;
temp.n[temp3].d=n.n[temp2].d;
temp3++;
temp2++;
}
}
else if(temp1<m.num&&temp2<n.num){
temp.n[temp3].row=n.n[temp2].row;
temp.n[temp3].col=n.n[temp2].col;
temp.n[temp3].d=n.n[temp2].d;
temp3++;
temp2++;
}
else if(temp1==m.num){
temp.n[temp3].row=n.n[temp2].row;
temp.n[temp3].col=n.n[temp2].col;
temp.n[temp3].d=n.n[temp2].d;
temp3++;
temp2++;
}
else if(temp2==n.num){
temp.n[temp3].row=m.n[temp1].row;
temp.n[temp3].col=m.n[temp1].col;
temp.n[temp3].d=m.n[temp1].d;
temp1++;
temp3++;
}
}
temp.num=temp3;
cout<<temp.r<<" "<<temp.c<<" "<<temp.num<<endl;
for(int i=0;i<temp.num;++i){
cout<<temp.n[i].row<<" "<<temp.n[i].col<<" "<<temp.n[i].d<<endl;
}
return 0;
}
文字编辑 (100 分)
题目
一篇文章由n个汉字构成,汉字从前到后依次编号为1,2,……,n。 有四种操作:
A i j表示把编号为i的汉字移动编号为j的汉字之前;
B i j表示把编号为i的汉字移动编号为j的汉字之后;
Q 0 i为询问编号为i的汉字之前的汉字的编号;
Q 1 i为询问编号为i的汉字之后的汉字的编号。
规定:1号汉字之前是n号汉字,n号汉字之后是1号汉字。
输入格式:
第1行,1个整数T,表示有T组测试数据, 1≤T≤9999.
随后的每一组测试数据中,第1行两个整数n和m,用空格分隔,分别代表汉字数和操作数,2≤n≤9999,1≤m≤9999;第2至m+1行,每行包含3个常量s、i和j,用空格分隔,s代表操作的类型,若s为A或B,则i和j表示汉字的编号,若s为Q,i代表0或1,j代表汉字的编号。
输出格式:
若干行,每行1个整数,对应每个询问的结果汉字编号。
输入样例:
在这里给出一组输入。例如:
1
9999 4
B 1 2
A 3 9999
Q 1 1
Q 0 3
输出样例:
在这里给出相应的输出。例如:
4
9998
思路
第三题,一开始不会,后来参考了大佬的代码,得知是跳舞链问题。
代码
#include<iostream>
using namespace std;
int main(){
int T;
int l[10001];
int r[10001];
char oper[3];
int x,y;
ios::sync_with_stdio(false);
cin.tie(0);
cin>>T;
int H,C;
for(int i=T;i>0;--i){
cin>>H>>C;
for(int j=1;j<=H;++j){
l[j]=j-1; //l数组为前驱的序号
r[j]=j+1; //r数组为后继的序号
}
l[1]=H;
r[H]=1;
for(int k=C;k>0;--k){
cin>>oper;
cin>>x>>y;
if(oper[0]=='A'){
r[l[x]]=r[x];
l[r[x]]=l[x];
r[x]=y;
l[x]=l[y];
r[l[x]]=x;
l[r[x]]=x;
}
else if(oper[0]=='B'){
r[l[x]]=r[x];
l[r[x]]=l[x];
l[x]=y;
r[x]=r[y];
r[l[x]]=x;
l[r[x]]=x;
}
else{
if(x==0){
cout<<l[y]<<"\n";
}
else cout<<r[y]<<"\n";
}
}
}
return 0;
}
幸福指数 (100 分)
题目
人生中哪段时间最幸福?幸福指数可能会帮你发现。幸福指数要求:对自己每天的生活赋予一个幸福值,幸福值越大表示越幸福。一段时间的幸福指数就是:这段时间的幸福值的和乘以这段时间的幸福值的最小值。幸福指数最大的那段时间,可能就是人生中最幸福的时光。
输入格式:
第1行,1个整数n,, 1≤n≤100000,表示要考察的天数。
第2行,n个整数Hi,用空格分隔,Hi表示第i天的幸福值,0≤n≤1000000。
输出格式:
第1行,1个整数,表示最大幸福指数。
第2行,2个整数l和r,用空格分隔,表示最大幸福指数对应的区间[l,r]。如果有多个这样的区间,输出最长最左区间。
输入样例:
在这里给出一组输入。例如:
7
6 4 5 1 4 5 6
输出样例:
在这里给出相应的输出。例如:
60
1 3
思路
第四题,是一个单调栈问题,我使用了两个栈,分别用来存储数列中某一个数字左边和右边第一个比它小的数字。并且使用了一个数组add,求出到n项(假设此刻为第n项)的和,最后用来相乘,得出题解。
注意!:
1.要将第0项和第n+1项置为负数,避免发生找不到比自己小的数的情况。
2.注意要输出最长最左区间,要设置两个条件约束最长和最左。
代码
#include<iostream>
#include<stack>
using namespace std;
long long ans[100004];
long long add[100004];
long long temp=0;
long long key=0;
long long ll;
long long rr;
long long l[100004],r[100004];
int main(){
stack<int>lsmal;
stack<int>rsmal;
int num;
ios::sync_with_stdio(false);
cin.tie(0);
cin>>num;
ans[0]=ans[num+1]=-1;
for(int i=1;i<=num;++i){
cin>>ans[i];
add[i]=add[i-1]+ans[i];
}
lsmal.push(0);
for(int i=1;i<=num;++i){
while(!lsmal.empty()&&ans[lsmal.top()]>=ans[i]){
lsmal.pop();
}
l[i]=lsmal.top();
lsmal.push(i);
}
rsmal.push(num+1);
for(int i=num;i>=1;--i){
while(!rsmal.empty()&&ans[rsmal.top()]>=ans[i]){
rsmal.pop();
}
r[i]=rsmal.top();
rsmal.push(i);
}
for(int i=1;i<=num;++i){
temp=(add[r[i]-1]-add[l[i]])*ans[i];
if(temp>key){
key=temp;
ll=l[i]+1;
rr=r[i]-1;
}
else if(temp==key&&rr-ll<r[i]-1-l[i]-1){
ll=l[i]+1;
rr=r[i]-1;
}
else if(temp==key&&l[i]+1<ll){
ll=l[i]+1;
rr=r[i]-1;
}
}
cout<<key<<"\n"<<ll<<" "<<rr<<"\n";
}