Codeforces 611F 思维

Codeforces 611F
题目链接:
http://codeforces.com/problemset/problem/611/F
题意:
有一个矩阵(500000 * 500000)。
现在有一个操作序列(500000),可以使一个格子上下左右走。问每个格子需要走操作序列(走到尾巴循环至开始)上几个操作可以碰到边界。如果有格子碰不到输出-1.
源码:
/*
基本照T神改的。
把问题转化成每次消除一个矩形上的那些边。
记录一个点向左向右、向上向下偏移原位置的坐标偏移值miny,maxy,minx,maxx
每次更新这四个值时,说明消去了矩阵的一条边界。

一次消除过后,在这个基础上进行第二次消除。容易证明第二次消除时会产生消除的地方第三次也会产生消除。

然后把这些消除排个序,一个个按顺序执行就可以。

*/

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <string>
#include <queue>
using namespace std;
#define LL long long
#define MOD (1000000007)
const int MAXN = 500000 + 5;
char op[MAXN];
void operation(char c, int &x, int &y)
{
    if(c == 'R')    y--;
    else if(c == 'L')    y++;
    else if(c == 'U')    x++;
    else    x--;
}
int Type(char c)
{
    if(c == 'R' || c == 'L')    return 0;
    else    return 1;
}
struct D
{
    LL num;
    int type;
    D(){}
    D(int _type,LL _num ){num = _num, type = _type;}
};
vector<D>v1, v2, v11, v22;
int main()
{
    int n, r, c;
    while(scanf("%d%d%d", &n, &r, &c) != EOF){
        scanf("%s", op);
        v1.clear(); v11.clear();
        v2.clear(); v22.clear();
        int minx, miny, maxx, maxy;
        minx = miny = maxx = maxy = 0;
        int nowx= 0, nowy = 0;

        for(int i = 0 ; i < n ; i++){
            operation(op[i], nowx, nowy);
            int type = Type(op[i]);
            if(type == 0){
                if(maxy < nowy) maxy = nowy;
                else if(miny > nowy) miny = nowy;
                else    continue;
                v1.push_back(D(type, i + 1));
//                printf("first\n");
            }
            else{
                if(maxx < nowx) maxx = nowx;
                else if(minx > nowx) minx = nowx;
                else continue;
                v2.push_back(D(type, i + 1));
//                printf("second\n");
            }
//            printf("i = %d, nowx = %d, nowy = %d\n", i, nowx, nowy);
//            printf("minx = %d, maxx = %d, miny = %d, maxy = %d\n\n", minx, maxx, miny, maxy);
        }
        for(int i = 0 ; i < n ; i++){
            operation(op[i], nowx, nowy);
            int type = Type(op[i]);
            if(type == 0){
                if(maxy < nowy) maxy = nowy;
                else if(miny > nowy) miny = nowy;
                else    continue;
                v11.push_back(D(type, i + 1 + n));
//                printf("first\n");
            }
            else{
                if(maxx < nowx) maxx = nowx;
                else if(minx > nowx) minx = nowx;
                else    continue;
                v22.push_back(D(type, i + 1 + n));
//                printf("second\n");
            }
//            printf("i = %d, nowx = %d, nowy = %d\n", i, nowx, nowy);
//            printf("minx = %d, maxx = %d, miny = %d, maxy = %d\n\n", minx, maxx, miny, maxy);
        }
//        printf("v11.size() = %d, v22.size() = %d\n", (int)v11.size(), (int)v22.size());
        if(v11.size()){
            while(v1.size() < c){
                for(int j = 0 ; j < (int)v11.size() ; j++){
                    v1.push_back(v11[j]);
                    v11[j].num += n;
                    if(v1.size() >= c)  break;
                }
            }
        }
        if(v22.size()){
            while(v2.size() < r){
                for(int j = 0 ; j < (int)v22.size() ; j++){
                    v2.push_back(v22[j]);
                    v22[j].num += n;
                    if(v2.size() >= r)  break;
                }
            }
        }
        LL ans = 0;
        int f1 = 0, f2 = 0;
//        printf("v1.size() = %d, v2.size() = %d\n", v1.size(), v2.size());
        while(f1 < v1.size() || f2 < v2.size()){
            int flag = 0;
            if(f2 == v2.size()) flag = 1;
            else if(f1 < v1.size() && v1[f1].num < v2[f2].num)  flag = 1;
//            printf("flag = %d\n", flag);
            if(flag){
                ans = (ans + v1[f1++].num * r % MOD) % MOD;
                c--;
//                printf("v1[f1].num = %I64d\n", v1[f1 - 1].num);
            }
            else{
                ans = (ans + v2[f2++].num * c % MOD) % MOD;
//                printf("v2[f2].num = %I64d\n", v2[f2 - 1].num);
                r--;
            }
            if(r <= 0 || c <= 0)    break;
//            printf("r = %d, c = %d, ans = %I64d\n", r, c, ans);
//            system("pause");
        }
        if(r && c)  printf("-1\n");
        else    printf("%I64d\n", ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值