T1:数列查询
这道题最多查询10000次,若单纯使用递归,会有多次重复计算的过程,所以可以用一个数组存放递归过程中计算得到的结果。在查询f(i)时,如果f(i)之前已经计算过了,直接输出即可;若没计算过,则进行计算并存放到数组中。
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int f[1000000+9];
int F(int x){
if(f[x])return f[x];
else if(x==1)return f[1]=10;
else return f[x]=F(x-1)*11/10;
}
int q;
int main(){
scanf("%d",&q);
int x;
for(int i=0;i<q;i++){
scanf("%d",&x);
printf("%d\n",F(x));
}
return 0;
}
T2:稀疏矩阵之差
这道题是用三元组表示的,输入矩阵时是按行列排序输入的,所以直接存放即可,不用再进行排序。若A,B的行列数不同,则直接输出"Illegal!"。计算A-B时,从头开始进行操作,分别用pa,pb指向A,B当前要进行操作的元素,如果A[pa],B[pb]行列相同,则比较二者的值,若相减为0,则不存放到C中,若不为0,则存放到C中,cnt++(cnt记录矩阵C中非0数据项的个数)。若A[pa],B[pb]行列不相同,则按照先行后列的顺序,对优先级高的进行操作,存放到C中,cnt++,同时,这个矩阵(指刚刚优先级高的数据所在的矩阵)的指针(pa/pb)移动到下一位,另一个没有进行操作的矩阵,指针不变。
代码如下:
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
using namespace std;
int N1,M1,t1,N2,M2,t2;
int cnt;
struct node{
int x,y;
int data;
};
node a[50000+5],b[50000+5],c[500000+5];
void work(){
if(!((N1==N2)&&(M1==M2))){
printf("Illegal!");
exit(0);
}else{
int pa=0,pb=0,j;
for(j=0;pa<t1&&pb<t2;){
if(a[pa].x==b[pb].x&&a[pa].y==b[pb].y){ //行列相同时
if(a[pa].data==b[pb].data); //相减为0,不存放
else{
c[j].x=a[pa].x;
c[j].y=a[pa].y;
c[j].data=a[pa].data-b[pb].data;
j++;
}
pa++;pb++;
}else if(a[pa].x==b[pb].x){
if(a[pa].y<b[pb].y){
c[j].x=a[pa].x;
c[j].y=a[pa].y;
c[j].data=a[pa].data;
pa++;
}else{
c[j].x=b[pb].x;
c[j].y=b[pb].y;
c[j].data=-b[pb].data;
pb++;
}
j++;
}else if(a[pa].x<b[pb].x){
c[j].x=a[pa].x;
c[j].y=a[pa].y;
c[j].data=a[pa].data;
pa++;
j++;
}else{
c[j].x=b[pb].x;
c[j].y=b[pb].y;
c[j].data=-b[pb].data;
pb++;
j++;
}
}
cnt=j;
if(pa>=t1&&pb>=t2)return;
else if(pa>=t1){
for(;pb<t2;j++,pb++){
c[j].x=b[pb].x;
c[j].y=b[pb].y;
c[j].data=-b[pb].data;
}
}else{
for(;pa<t1;j++,pa++){
c[j].x=a[pa].x;
c[j].y=a[pa].y;
c[j].data=a[pa].data;
}
}
cnt=j;
}
}
void print(){
printf("%d %d %d\n",N1,M1,cnt);
for(int i=0;i<cnt;i++){
printf("%d %d %d\n",c[i].x,c[i].y,c[i].data);
}
}
int main(){
scanf("%d%d%d",&N1,&M1,&t1);
int x,y;
long long data;
for(int i=0;i<t1;i++){
scanf("%d%d%d",&x,&y,&data);
a[i].x=x;
a[i].y=y;
a[i].data=data;
}
scanf("%d%d%d",&N2,&M2,&t2);
for(int i=0;i<t2;i++){
scanf("%d%d%d",&x,&y,&data);
b[i].x=x;
b[i].y=y;
b[i].data=data;
}
work();
print();
return 0;
}
T3:文字编辑
这道题是跳舞链的应用。
代码如下:
#include<iostream>
#include<cstdio>
using namespace std;
int t; //有t组测试数据
int n,m;
int Left[10000+8],Right[10000+8];
// Left[i]表示编号为 i 的汉字的前一个汉字的编号
/// Right[i] 表示编号为 i 的汉字的后一个汉字的编号
int main(){
scanf("%d",&t);
char s;
int x,y;
for(int i=0;i<t;i++){
scanf("%d%d",&n,&m);
for(int j=1;j<=n;j++){ //初始化
Left[j]=j-1;
Right[j]=j+1;
}
Left[1]=n;
Right[n]=1;
for(int j=0;j<m;j++){
scanf("\n%c%d%d",&s,&x,&y);
/* 读入时前面加回车,否则会将上一个操作的回车当作操作数读进来。或者直接用字符串读也可以,因为使用 %s 读入字符串的时候会自动忽略回车、空格等空白字符。*/
if(s=='A'){
Right[Left[x]]=Right[x]; //跳舞脱离原链
Left[Right[x]]=Left[x];
Right[Left[y]]=x;
Left[x]=Left[y];
Left[y]=x;
Right[x]=y;
}else if(s=='B'){
Right[Left[x]]=Right[x]; //跳舞脱离原链
Left[Right[x]]=Left[x];
Left[Right[y]]=x;
Right[x]=Right[y];
Right[y]=x;
Left[x]=y;
}else{
if(x==0){
printf("%d\n",Left[y]);
}else{
printf("%d\n",Right[y]);
}
}
}
}
return 0;
}
T4:幸福指数
用Day数组存放每天的幸福值,Pre存放幸福值的前缀和。对每一个元素Day[i],找以Day[i]为最小值的区间,即找Day[i]左边和右边第一个比其小的元素。因此我们可以用单调栈来维护,然后用数组L[i],R[i]分别存放左边右边第一个比其小的元素的下标,最后再进行比较。但要注意题目要求最长最左区间,所以要单独判断一下。(要用long long)
代码如下:
#include<iostream>
#include<cstdio>
#include<stack>
#define MAX 10000000
using namespace std;
int n;
long long ans;
int FL,FR;
int L[MAX],R[MAX];
long long Day[MAX],Pre[MAX];
stack<int> s; //s存放下标
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&Day[i]);
Pre[i]=Pre[i-1]+Day[i];
}
Day[0]=-100;Day[n+1]=-100;
s.push(0);
for(int i=1;i<=n;i++){
while(Day[s.top()]>=Day[i]) s.pop();
L[i]=s.top();
s.push(i);
}
while(!s.empty())s.pop();
s.push(n+1);
for(int i=n;i>=1;i--){
while(Day[s.top()]>=Day[i])s.pop();
R[i]=s.top();
s.push(i);
}
ans=Day[1];
FL=FR=1;
for(int i=1;i<=n;i++){
long long tmp=(Pre[R[i]-1]-Pre[L[i]])*Day[i];
if(ans<tmp){
ans=tmp;
FL=L[i]+1;
FR=R[i]-1;
}else if(ans==tmp){
int dl=L[i]+1;
int dr=R[i]-1;
if(FR-FL<dr-dl){ //判断最长
FR=dr;
FL=dl;
}else if(dr-dl==FR-FL){ //判断最左
if(dl<FL){
FL=dl;
FR=dr;
}
}
}
}
printf("%lld\n%d %d",ans,FL,FR);
return 0;
}