【掃描法】Meteor UVALive - 3905
阿新 • • 發佈:2021-08-20
分析
將每個點進出矩形的時間的左右區間 \([L, R]\) 處理出來,這樣就可以在一維的時間軸做掃描法了。
細節&技巧:
-
注意到在矩形邊界的點不計入貢獻,因此處理出來的時間區間均為開區間,在維護貢獻 \(cnt\) 之前的排序中,在時間點相等的時候,指定出隊的點優先順序更高以使貢獻被正確維護。
-
在
update
操作中出現了除數運算,如果需要避免使用double
,可以利用所有可能出現的速度的最小公倍數 \(lcm\)。注意到題目中速度的範圍在 \([1,10]\),因此 \(lcm=2520\)。只需將時間乘上 \(lcm\) 即可避免使用double
。
#pragma GCC optimize("O3") #include<bits/stdc++.h> using namespace std; #define endl '\n' #define debug(x) cerr << #x << ": " << x << endl #define pb push_back #define eb emplace_back #define set0(a) memset(a,0,sizeof(a)) #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define INF 0x3f3f3f3f #define ll_INF 0x7f7f7f7f7f7f7f7f using pii = pair<int, int>; using pdd = pair<double, double>; using vi = vector<int>; using vvi = vector<vi>; using vb = vector<bool>; using vpii = vector<pii>; using ll = long long; using ull = unsigned long long; #define int ll inline void read(int &x) { int s=0;x=1; char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-')x=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar(); x*=s; } const int N=1e5+5, D=2520; int w, h; int n; struct Event{ int x, type; bool operator < (const Event &o)const{ return x==o.x? type<o.type: x<o.x; } }e[N<<1]; int tot; void update(int x, int v, int p, int &L, int &R){ if(v==0){ if(x<=0 || x>=p) L=INF, R=-INF; } else if(v>0) L=max(L, -x*D/v), R=min(R, (p-x)*D/v); else L=max(L, (x-p)*D/-v), R=min(R, x*D/-v); } signed main(){ int T; cin>>T; while(T--){ read(w), read(h); read(n); tot=0; rep(i,1,n){ int x, y, a, b; read(x), read(y), read(a), read(b); int L=0, R=INF; // time of in and out update(x, a, w, L, R); // x axis of in and out update(y, b, h, L, R); // y axis of in and out if(L<R) e[++tot]={L, 1}, e[++tot]={R, -1}; } sort(e+1, e+1+tot); int res=0, cnt=0; rep(i,1,tot){ cnt+=e[i].type; res=max(res, cnt); } cout<<res<<endl; } return 0; }