CSU-2214 Sequence Magic

题目链接

http://acm.csu.edu.cn:20080/csuoj/problemset/problem?pid=2214

题目

Description

有一个1到N的自然数序列1,2,3,...,N-1,N。

我们对它进行M次操作,每次操作将其中连续的一段区间 [Ai,Bi][Ai,Bi] (即第Ai个元素到第Bi个元素之间的一段)取出,然后插入到剩下的第Ci个元素的后面,如果Ci=0,表示插入到最左端。

现在,M次操作完后,有K个询问,每个询问Pi表示询问最终第Pi个元素是几。你的任务是写一个程序,依次回答这K个询问。

Input

第一行三个数,N,M,K。

接下来M行,每行三个整数Ai,Bi,Ci。

接下来K行,每行一个正整数Pi。

1<=N<=\(10^9\),1<=M<=\(10^4\),1<=K<=1000,1<=Ai<=Bi<=N,0<=Ci<=N-(Bi-Ai+1),1<=Pi<=N;

Output

输出共K行,为每次询问的答案。

Sample Input

13 3 13 
6 12 1 
2 9 0 
10 13 8 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13

Sample Output

6 
7 
8 
9 
10 
11 
12
2 
3 
4 
5 
13 
1 

题解

由于k,m都很小,所以我们可以考虑离线的思想离线的思想,对于每一次询问,从m到1把区间平移操作恢复。我们要知道的是最后序列的第x个数,那么我们可以算出不做最后一次平移前x是第几个位置,这样倒退到第一次就是一开始x所在的位置,也就是x所对应的数,输出答案即可。

考虑一下怎么算,有两种情况\(c[j] \ge a[j]\)时,我们把\(a[j]...b[j]\)移动到\(c[j]\)后面,此时若x在\(a[j],c[j]\)之间,那么他就会向后移动\(b[j]-a[j]+1\)个数,如果它在\(c[j]+1,c[j]+b[j]-a[j]+1\)之间,那么设这次位置是x,恢复平移后位置为y,那么\(a[j]+(x-c[j])-1=y\),即x+=a[j]-c[j]-1。其他情况x不变

\(c[j]<a[j]\),此时若x在\(c[j]+1,c[j]+b[j]-a[j]+1\)之间,那么x+=a[j]-c[j]-1,若x处在\(c[j]+1+b[j]-a[j]+1,b[j]\)之间,那么\(x=c[j]+x-(c[j]+b[j]-a[j]+1)\)即x+=a[j]-b[j]-1。

一直倒推到1即为答案,依次输出即可

AC代码

#include<bits/stdc++.h>
#define N 10050
using namespace std;
int a[N], b[N], c[N];
typedef long long ll;
int main() {
    int n, m, k;
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 1; i <= m; i++) {
        scanf("%d%d%d", &a[i], &b[i], &c[i]);
    }
    for (int i = 1; i <= k; i++) {
        ll x;
        scanf("%lld", &x);
        for (int j = m; j >= 1; j--) {
            if (c[j] >= a[j]) {
                if (x >= a[j] && x <= c[j]) {
                    x += b[j] - a[j] + 1;
                }
                else if (x >= c[j] + 1 && x <= c[j] + b[j] - a[j] + 1) {
                    x += a[j] - c[j] - 1;
                }
            }
            else {
                if (x >= c[j] + 1 && x <= c[j] + b[j] - a[j] + 1) {
                    x += c[j] + 1 + a[j] - c[j] - 1 - 1 - c[j];
                }
                else if (x >= c[j] + b[j] - a[j] + 1 + 1 && x <= b[j]) {
                    x -= (b[j] - a[j] + 1);
                }
            }
        }
        printf("%d\n", x);
    }
}
/**********************************************************************
    Problem: 2214
    User: Artoriax
    Language: C++
    Result: AC
    Time:284 ms
    Memory:2140 kb
**********************************************************************/

结语

至此所有寒假集训选拔写过的题的题解补完了,赶快开始补寒假集训的题解了,不能再划水了

转载于:https://www.cnblogs.com/artoriax/p/10372535.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值