洛谷 P8318 题解

题目传送门


题意:

给出一个长度为 \(n\) 的操作后的序列,然后给出 \(m\) 次操作过程,每次给出操作类型 \(op\)、操作数 \(x\)\(y\),求出操作前的原始序列。

在操作中,如果 \(x=y\),那么新的 \(x\) 就分别等于原始 \(x\)
两倍或平方。即:如果 \(op=1\),那么新的第 \(x\) 个元素就等于它的两倍;如果 \(op=2\),那么新的第 \(x\) 个元素就等于它的平方。


思路:

模拟题,但是坑点很多。

  • 由于给出的是操作后的序列,所以我们在还原时需要倒序还原,例如:\(n=2\),两次操作分别是 \(op1,x1,y1\)\(op2,x2,y2\)。那么我们就需要先还原 \(op2,x2,y2\) 再还原 \(op1,x1,y1\)

  • 同上,需要倒序还原,如果操作中是乘法,还原时就需要用除法,加减法同理。

  • 题目中还提到 \(x=y\) 的情况。当 \(op=1\) 时,原操作是将第 \(x\) 个元素 \(×2\),那么我们在还原时就需要将它 \(÷2\);同理,当 \(op=2\) 时,原操作是将第 \(x\) 个元素变成它的平方,那么我们在还原时就要将它进行 sqrt()


code:

#include <bits/stdc++.h>
using namespace std;

inline long long read(){
    long long s=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=s*10+ch-'0';
        ch=getchar();
    }
    return s*f;
}

int n,m;
long long a[1005];
int op[1005],x[1005],y[1005];

int main(){
    n=read();m=read();
    for(int i=1;i<=n;i++){
        a[i]=read();
    }
    for(int i=1;i<=m;i++){
        op[i]=read();x[i]=read();y[i]=read();
	}
    for(int i=m;i>=1;i--){ 
    	if(op[i]==1){
		    if(x[i]==y[i]){
		    	a[x[i]]/=2;
			}
			else{
	    		a[x[i]]-=a[y[i]];			
			} 


		}
		else{
		    if(x[i]==y[i]){
		    	a[x[i]]=sqrt(a[x[i]]);
			}
			else{
				a[x[i]]/=a[y[i]];
			}

		}
	}
    for(int i=1;i<=n;i++){
        printf("%lld ",a[i]);
    }
    return 0;
}
posted @ 2022-05-06 18:41  Black--Panda  阅读(71)  评论(0编辑  收藏  举报