1 条题解
-
0
自动搬运
来自洛谷,原作者为

Lieyiqi
AFO搬运于
2025-08-24 22:23:01,当前版本为作者最后更新于2023-12-28 13:45:15,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
设 表示输入多边形中的第 个 点, 表示
Mirko的查询点。如果 ,则在我们的多边形的第 条边上写入 ,否则写入 。那么现在有一个问题,“是否存在一对相反的边,但它们都写有 ”。
显然,不能暴力对每个查询都检查每条边上写的内容,因为这将导致 的算法复杂度。所以我们要创造一个高效的算法来解决这个问题。
不难看出,如果两条边上都写有 ,则它们之间的所有边(在一个方向上)也都写有 。
另外的,只有当一段连续的 的区间包含至少 个元素时,答案才是
DA。这是显而易见的,因为在 个连续的边中必定存在两条相对的边。现在,我们考虑一条任意的边及其相反边,并观察它们上写的值。如果它们都写有 ,则可以直接输出DA。如果它们都写有 ,则可以直接输出NE。如果其中一条边写有 ,另一条边写有 ,则我们可以将数组分为两部分,每部分以我们已检查的一条边开头。一部分的形式111...000,另一部分的形式为000...111。我们想在其中一部分找到最后一个 ,在另一部分找到第一个 。这可以用二分搜索快速完成。现在,我们已经找到了一个连续的 的区间的端点,并且可以检查条件是否成立。时间复杂度:。
// VS Code C/C++ #include<iostream> #include<cmath> #include<vector> #define I using #define AK namespace #define NOIP std; #define f1 first #define s2 second #define db double #define pb push_back #define FOR(i,a,b) for(int i=a;i<b;i++) I AK NOIP typedef long long ll; typedef pair<ll,ll> pll; int n; vector<pll> py; ll x,y; inline db cmp(pll a,pll b,pll c){ return db(a.f1)*(b.s2-c.s2)+ db(b.f1)*(c.s2-a.s2)+ db(c.f1)*(a.s2-b.s2); } inline bool get(int i){ return cmp(py[i],py[(i+1)%n],{x,y})>=0; } const string o[]={"NE","DA"}; inline int mj(int l,int r){ int li=l,hi=r,mid; while(li!=hi){ mid=(li+hi+1)/2; if(get(mid)==get(l)) li=mid; else hi=mid-1; } int ret=li-l+1; if(!get(l)) ret=n/2-ret; return ret; } inline bool solve(){ int mid=n/2; int a=get(0); int b=get(mid); if(a==b) return a; return mj(0,mid-1)+mj(mid,n-1)>mid; } signed main(){ ios::sync_with_stdio(false); int t; cin>>t>>n; FOR(i,0,n){ cin>>x>>y; py.pb({x,y}); } int q; ll da=0; cin>>q; FOR(i,0,q){ cin>>x>>y; x^=da*da*da*t; y^=da*da*da*t; int ans=solve(); da+=ans; cout<<o[ans]<<'\n'; } return 0; }
- 1
信息
- ID
- 5686
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者