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;
}