ABC-421-D - RLE Moving · znzryb
## 思路讲解
```cpp
// 整体思路就是我们如果发现如果两者起始位置不同,那么是不会有相交的,或者相交一次
// 简单而言,就是必须先有一次相交,接着运动方向一样,才能有相交,否则就直接穿过去了
```
```cpp
// 在同一点并且操作序列相同
if(a==b && opa==opb){
ans+=mn;
}else{
auto f=[&](ll dis){
Point c=oper(a, opa,dis),d=oper(b, opb, dis);
return mandis(c, d);
};
ll l=1,r=mn;
while (l<r) {
ll mid=l+r>>1;
// if(f(mid)<=f(mid+1)){
// 从mid点(或其前)开始,函数开始单调递增
if(f(mid+1)-f(mid)>=0){
r=mid;
}else{
l=mid+1;
}
}
if(f(l)==0){
++ans;
}
}
```
## AC代码
[https://atcoder.jp/contests/abc421/submissions/68978595](https://atcoder.jp/contests/abc421/submissions/68978595)
::: 源代码
```cpp
// by Gospel_rock
#include <bits/stdc++.h>
#include <deque>
#include <istream>
#include <vector>
#define all(vec) vec.begin(),vec.end()
#define PB push_back
#define EB emplace_back
#define EM emplace
#define FI first
#define SE second
#define pct __builtin_popcountll
#define ctz __builtin_ctzll
#define SZ(a) ((long long) a.size())
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)
#define debug(var) cerr << #var <<":"<<var<<"\n";
#define cend cerr<<"\n-----------\n"
#define fsp(x) fixed<<setprecision(x)
#define minn(vec) *min_element(vec.begin(),vec.end())
#define maxx(vec) *max_element(vec.begin(),vec.end())
using namespace std;
#ifdef LOCAL
template<typename T> void _print(T x) { cerr << x; }
// 可以打印多层数组,但是格式不是很好
template<typename T> void _print(vector<T> v) { cerr << "[ "; for (T i : v) _print(i), cerr << " "; cerr << "]"; }
template<typename T> void _print(set<T> s) { cerr << "{ "; for (T i : s) _print(i), cerr << " "; cerr << "}"; }
template<typename T, typename U> void _print(pair<T, U> p) { cerr << "{"; _print(p.first); cerr << ", "; _print(p.second); cerr << "}"; }
template<typename T, typename U> void _print(map<T, U> m) { cerr << "{ "; for (auto &p : m) _print(p), cerr << " "; cerr << "}"; }
// 打印两层数组,格式好一些
template<typename T> void _print(vector<vector<T>> v){cerr<<"{\n";for (auto i : v) _print(i), cerr << "\n";cerr<<" }";}
#endif
using ll = long long;using ull = unsigned long long;
using ld=double;using LD=long double;
using i128 = __int128;
using pdd = pair<ld,ld>;using plb = pair<ll,bool>;
using pll = pair<ll,ll>;using vll=vector<ll>;using vb=vector<bool>;
using tll = tuple<ll,ll,ll>;using vii=vector<int>;
using vpll = vector<pll>;using vtll = vector<tll>;
using vdb = vector<ld>;using vc=vector<char>;
using arr3 = array<ll,3> ;using arr2 = array<ll,2>;
using CD=complex<double>;
static constexpr ll MAXN=(ll)1e6+10,INF=(ll)1e17+3; // 1e17+3是素数 1e18+9是素数
static constexpr ll mod=(ll)1e9+7; // 998244353;
static constexpr double eps=1e-8;const double pi=acos(-1.0);
ll N,M,Q,X,K,T,lT,L;
inline void __();
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
// cin>>lT;
// while(lT--)
__();
return 0;
}
/*
*/
using Real = ll;
int sgn(Real x) {
if (-eps < x && x < eps) return 0;
return x < 0 ? -1 : 1;
}
struct Point{
Real x,y;
Point(){}
Point(Real x,Real y):x(x),y(y){}
// & 是指只对左值起效果,不能对Point(1,2)这样的临时值
// friend Point& operator+=(Point &a,Point b){
// a.x+=b.x;
// a.y+=b.y;
// return a;
// }
friend Point operator +(Point a,Point b){
return Point(a.x+b.x,a.y+b.y);
}
friend Point operator -(Point a,Point b){
return Point(a.x-b.x,a.y-b.y);
}
friend bool operator <(Point a,Point b) {
return sgn(a.x-b.x)?a.x<b.x:a.y<b.y;
}
friend bool operator ==(Point a,Point b){
if(sgn(a.x-b.x)) return false;
if(sgn(a.y-b.y)) return false;
return true;
}
friend Point operator *(Point a,Real k){
return Point(a.x*k,a.y*k);
}
friend Point operator /(Point a,Real k){
return Point(a.x/k,a.y/k);
}
friend bool operator !=(Point a,Point b){
return !(a==b);
}
friend istream& operator >>(istream& is,Point &e){
Real a,b;is>>a>>b;
e=Point(b,a);
return is;
}
friend ostream &operator<<(ostream &os, Point p) {
return os << "(" << p.x << ", " << p.y << ")";
}
};
Real cross(Point a,Point b){
return a.x*b.y-a.y*b.x;
}
Real cross(Point p1, Point p2, Point p0) { // 叉乘 (p1 - p0) x (p2 - p0);
return cross(p1 - p0, p2 - p0);
}
Real dot(Point a,Point b){
return a.x*b.x+a.y*b.y;
}
Real mandis(Point a,Point b){
Real res=abs(a.x-b.x)+abs(a.y-b.y);
return res;
}
// 采用两点式
struct Line{
Point p,q;
Line(){}
Line(Point a,Point b):p(a),q(b) {}
friend bool operator<(Line a,Line b){
if(a.p!=b.p) return a.p<b.p;
return a.q<b.q;
}
friend bool operator==(Line a,Line b){
if(a.p!=b.p) return false;
if(a.q!=b.q) return false;
return true;
}
friend istream& operator>>(istream& is, Line& e) {
Real a,b,c,d;
is >> a >> b >> c >> d;
e = Line(Point(a,b),Point(c,d));
return is;
}
friend ostream&operator<<(ostream &os, Line l) {
return os << "<" << l.p << ", " << l.q << ">";
}
};
// p+tv=q+sw
// (p-q) x w+tv x w = 0
// t=-(p-q)x w/(vxw)
// 传入的是方向式 拿到的是两直线交点
Point getintersect(const Line &a,const Line &b){
Point p=a.p, v=a.q-a.p,q=b.p,w=b.q-b.p;
Point u=p-q;
ld t=cross(w,u)/cross(v,w);
return p+v*t;
}
bool seginterline(Line seg,Line e){
if(sgn(cross(e.p-seg.p, e.q-seg.p))*sgn(cross(e.p-seg.q, e.q-seg.q))>0){
return false;
}
return true;
}
bool onseg(Point p,Line s){
return sgn(cross(p-s.p, p-s.q))==0 && sgn(dot(p-s.p,p-s.q))<=0;
}
// AC https://vjudge.net/problem/OpenJ_Bailian-1410
bool seginterseg(Line l1, Line l2) {
Point s1 = l1.p, e1 = l1.q;
Point s2 = l2.p, e2 = l2.q;
// s2 相对于 s1->e1 其在哪一侧?
int o1 = sgn(cross(e1, s2, s1));
int o2 = sgn(cross(e1, e2, s1));
int o3 = sgn(cross(e2, s1, s2));
int o4 = sgn(cross(e2, e1, s2));
// 防止把共线但不重叠的两线段判定为相交
if (o1 == 0 && onseg(s2, l1)) return true;
if (o2 == 0 && onseg(e2, l1)) return true;
if (o3 == 0 && onseg(s1, l2)) return true;
if (o4 == 0 && onseg(e1, l2)) return true;
// 需要都在不同侧
return (o1 * o2 < 0) && (o3 * o4 < 0);
}
Point oper(Point a,char op,ll dis){
if(op=='U'){
a.y-=dis;
}else if(op=='D'){
a.y+=dis;
}else if(op=='R'){
a.x+=dis;
}else{
a.x-=dis;
}
return a;
}
struct OP{
char op;ll dis;
friend istream& operator >>(istream &is,OP &e){
is>>e.op>>e.dis;
return is;
}
};
inline void __(){
Point a,b;
cin>>a>>b;
cin>>N>>M>>L;
// 整体思路就是我们如果发现如果两者起始位置不同,那么是不会有相交的,或者相交一次
// 简单而言,就是必须先有一次相交,接着运动方向一样,才能有相交,否则就直接穿过去了
// vector<OP> A(N+5),B(N+5);
queue<OP> A,B;
FOR(i,1,M){
OP a;
cin>>a;
A.push(a);
}
FOR(i,1,L){
OP b;
cin>>b;
B.push(b);
}
ll ans=0;
while (!A.empty()) {
auto [opa,disa]=A.front();
auto [opb,disb]=B.front();
ll mn=min(disa,disb);
A.front().dis-=mn;B.front().dis-=mn;
if(A.front().dis==0){
A.pop();
}
if(B.front().dis==0){
B.pop();
}
if(a==b && opa==opb){
ans+=mn;
}else{
auto f=[&](ll dis){
Point c=oper(a, opa,dis),d=oper(b, opb, dis);
return mandis(c, d);
};
ll l=1,r=mn;
while (l<r) {
ll mid=l+r>>1;
// if(f(mid)<=f(mid+1)){
// 从mid点(或其前)开始,函数开始单调递增
if(f(mid+1)-f(mid)>=0){
r=mid;
}else{
l=mid+1;
}
}
if(f(l)==0){
++ans;
}
}
a=oper(a, opa, mn);
b=oper(b, opb, mn);
}
cout<<ans;
}
/*
AC
https://atcoder.jp/contests/abc421/submissions/68978595
*/
```
:::
## 心路历程(WA,TLE,MLE……)