QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#697173 | #7015. Rikka with Illuminations | pengpeng_fudan | AC ✓ | 156ms | 3884kb | C++23 | 9.9kb | 2024-11-01 11:37:52 | 2024-11-01 11:37:52 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
using ll =long long;
//注意叉乘是否会爆ll
//注意凸包的最后一个点都是第一个点
//注意凸包都是逆时针的
//注意每次选凸包基准点都是x最小然后y最大
template<class T>
struct vec{
T x,y;
vec(T _x=0,T _y=0):x(_x),y(_y){};
int qx(){//四一二三排序,按需修改
if(x>=0&&y>=0) return 2;
if(x<0&&y>=0) return 3;
if(x<0&&y<0) return 4;
if(x>=0&&y<0) return 1;
return -1;
}
void print(){cerr<<x<<' '<<y<<'\n';}
bool operator<(vec a){
if(qx()!=a.qx()) return qx()<a.qx();
else{
T p=x*a.y,q=y*a.x;
if(p!=q) return p>q;
else if(a.y==0) return abs(x)>abs(a.x);
else return abs(y)>abs(a.y);
}
}
T len2(){return x*x+y*y;}
vec operator *(T k){return {x*k,y*k};}
vec operator +(vec a){return {x+a.x,y+a.y};}
vec operator -(vec a){return {x-a.x,y-a.y};}
T operator *(vec a){return x*a.x+y*a.y;}
T operator ^(vec a){return x*a.y-y*a.x;}
bool operator ==(vec a){return x==a.x&&y==a.y;}
bool operator !=(vec a){return (x!=a.x||y!=a.y);}
};
template<class T>
bool check_on_line_dir(vec<T> p,vec<T> q){
vec<__int128_t> p1={p.x,p.y};
vec<__int128_t> q1={q.x,q.y};
if((p1*q1)>=0&&(p1^q1)==0) return true;
return false;
}
template<class T>
vector<vec<T>> build_convex(vector<vec<T>> pot){//输入点集输出凸包(最后一个点和第一个点是一个点)
sort(pot.begin(),pot.end(),[&](vec<T> a,vec<T> b){if(a.x!=b.x) return a.x<b.x;return a.y>b.y;});
int n=pot.size();
int lo=0;
vector<vec<T>> res;
for(int i=0;i<n;i++){
while(lo>=2&&((res[lo-1]-res[lo-2])^(pot[i]-res[lo-1]))<=0) lo--,res.pop_back();
res.push_back(pot[i]),lo++;
}
int pre=lo;
for(int i=n-2;i>=0;i--){
while(lo>=pre+1&&((res[lo-1]-res[lo-2])^(pot[i]-res[lo-1]))<=0) lo--,res.pop_back();
res.push_back(pot[i]),lo++;
}
return res;
}
template<class T>
double convex_peri(vector<vec<T>> convex){//输入凸包(最后一个点和第一个点是一个点),输出凸包长度
double len=0;
int sz=convex.size();
for(int i=1;i<=sz-1;i++){
len+=sqrt((convex[i]-convex[i-1]).len2());
}
return len;
}
template<class T>
double convex_area(vector<vec<T>> convex){//输入凸包(最后一个点和第一个点是一个点),输出凸包面积
T area=0;
int sz=convex.size();
for(int i=0;i<sz-2;i++){
area+=abs((convex[0]-convex[i+1])^(convex[0]-convex[i+2]));
}
return (double)area/2;
}
//https://tsinghua.contest.codeforces.com/group/3T118PLOiT/contest/544779/problem/I
template<class T>
void reorder(vector<vec<T>>& p){//将凸包变成先x最小再y最小,输入需要满足(最后一个点和第一个点是一个点)
p.pop_back();
rotate(p.begin(), min_element(p.begin(),p.end(), [&](vec<T> a, vec<T> b) {
return make_pair(a.x, -a.y) < make_pair(b.x, -b.y);
}), p.end());p.push_back(p[0]);
}
template<class T>
vector<vec<T>> mincowsky_sum(vector<vec<T>> a,vector<vec<T>> b){//传入的是两个已经建好的且为逆时针的凸包(最后一个点和第一个点是一个点)//注意输出的凸包的相邻两个边可能是平行的
reorder(a),reorder(b);//让a和b的第0个点是x最小然后y最大
vector<vec<T>> res;
vec<T> st=a[0]+b[0];
int s1=a.size(),s2=b.size();
int l1=0,l2=0;
res.push_back(st);
while(l1!=s1-1||l2!=s2-1){
if(l1==s1-1||(l2!=s2-1&&b[l2+1]-b[l2]<a[l1+1]-a[l1])){
st=st+(b[l2+1]-b[l2]);l2++;
}
else {
st=st+(a[l1+1]-a[l1]);l1++;
}
res.push_back(st);
}
return res;
}
template<class T>
struct line{
vec<T> k,b;//k为方向,b为线上任意一个点,射线的话b为端点
line(vec<T> dir,vec<T> pot):k(dir),b(pot) {}
};
template<class T>
vec<double> getnode(line<T> p,line<T> q){
assert((p.k^q.k)!=0);
double t=(double)((p.b-q.b)^q.k)/(q.k^p.k);
vec<double> ans;
ans.x=p.b.x+p.k.x*t;
ans.y=p.b.y+p.k.y*t;
return ans;
};
template<class T>
struct convex_hull_trick{//静态凸包求单点值
vector<line<T>> convex;// 注意line.b不是射线端点,存的仅仅是直线在凸包上的顺序
bool _mo;
convex_hull_trick(vector<line<T>> line_all,int mo){//mo=1求极大,mo=0求极小
_mo=mo;
for(auto& [k,b]:line_all){
assert(k.x);
if(k.x<0) {k.x=-k.x,k.y=-k.y;}
}
line<T> line_y(vec<T>(0,1),vec<T>(0,0));
if(mo==0) sort(line_all.begin(),line_all.end(),[&](line<T> a,line<T> b){
if(!check_on_line_dir(a.k,b.k)) return b.k<a.k;
else return getnode(line_y,a).y<getnode(line_y,b).y;
});
else sort(line_all.begin(),line_all.end(),[&](line<T> a,line<T> b){
if(!check_on_line_dir(a.k,b.k)) return a.k<b.k;
else return getnode(line_y,a).y>getnode(line_y,b).y;
});
int sz=line_all.size();
int lo=0;
for(int i=0;i<sz;i++){
if(i==0) {convex.push_back(line_all[i]);lo++;continue;}
if(check_on_line_dir(line_all[i].k,line_all[i-1].k)) continue;
while(lo>1){
if(getnode(convex[lo-2],convex[lo-1]).x>=getnode(convex[lo-1],line_all[i]).x) {
lo--;convex.pop_back();
}
else break;
}
convex.push_back(line_all[i]);lo++;
}
}
double get_y(double x){
int lo=0,ro=(int)convex.size()-1;
while(lo<ro){
int mid=(lo+ro)>>1;
if(getnode(convex[mid],convex[mid+1]).x<=x) lo=mid+1;
else ro=mid;
}
return convex[lo].b.y+convex[lo].k.y/convex[lo].k.x*(x-convex[lo].b.x);
}
};
const double eps=1e-9;
template<class T>
double half_plane(vector<line<T>> line_all){//半平面交,目标面积必须在输入有向线段左边
vector<vec<double>> convex;
line<T> line_y(vec<T>(0,1),vec<T>(0,0));
sort(line_all.begin(),line_all.end(),[&](line<T> a,line<T> b){
if(!check_on_line_dir(a.k,b.k)) return a.k<b.k;
else return ((b.b-a.b)^a.k)>0;
});
int lo=0,ro=-1;
vector<line<T>> res;
auto check=[&](line<T> l,line<T> mid,line<T> r)->bool {//l,mid的交点在r左边
return ((getnode(l,mid)-vec<double>(r.b.x,r.b.y))^vec<double>(r.k.x,r.k.y))<eps;
};
int sz=line_all.size();
for(int i=0;i<sz;i++){
if(i==0) {res.push_back(line_all[i]);ro++;continue;}
if(check_on_line_dir(line_all[i].k,line_all[i-1].k)) continue;
while(lo<ro&&!check(res[ro-1],res[ro],line_all[i])) {res.pop_back();ro--;}
while(lo<ro&&!check(res[lo],res[lo+1],line_all[i])) lo++;
res.push_back(line_all[i]);ro++;
}
while(lo<ro&&!check(res[ro-1],res[ro],res[lo])) ro--;
if(ro-lo<=1) return 0;
if(!check(res[ro],res[lo],res[lo+1])) return -1;
for(int i=lo;i<=ro-1;i++) convex.push_back(getnode(res[i],res[i+1]));
convex.push_back(getnode(res[ro],res[lo]));convex.push_back(convex[0]);
return convex_area(convex);
}
pair<int,int> get_pot_convex_cut_line(vec<ll> v,vector<vec<ll>>& hull){//要传引用否则复杂度不对,sz-1和0是同一个点所以返回时把sz-1变成0了
int sz=hull.size();
int lo=0,ro=sz-2;
int flag=((((hull[1]-v)^(hull[0]-v))>=0)?1:-1);
while(lo<ro){
int mid=(lo+ro+1)>>1;
if((((hull[mid]-v)^(hull[0]-v))*flag)>=0) lo=mid;
else ro=mid-1;
}
pair<int,int> lcut={0,lo},rcut={lo+1,sz-1};
pair<int,int> ans;
if(flag==1) swap(lcut,rcut);
lo=lcut.first,ro=lcut.second;
while(lo<ro){
int mid=(lo+ro)>>1;
if(((hull[mid+1]-hull[mid])^(v-hull[mid]))>=0) lo=mid+1;
else ro=mid;
}
ans.first=(lo==sz-1?0:lo);
lo=rcut.first,ro=rcut.second;
while(lo<ro){
int mid=(lo+ro)>>1;
if(((hull[mid+1]-hull[mid])^(hull[mid]-v))>0) lo=mid+1;
else ro=mid;
}
ans.second=(lo==sz-1?0:lo);
return ans;
}
void solve(void) {
int n,m;
cin>>n>>m;
vector<vec<ll>> hull;
for(int i=0;i<n;i++){
int x,y;
cin>>x>>y;hull.push_back({x,y});
}
hull.push_back(hull[0]);
vector<pair<int,int>> maxn(2*n+1);
for(int i=1;i<=m;i++){
vec<ll> v;cin>>v.x>>v.y;
pair<int,int> res=get_pot_convex_cut_line(v,hull);
// cerr<<res.first<<' '<<res.second<<'\n';
if(res.first<=res.second) {
maxn[res.first]=max(maxn[res.first],{res.second,i});
maxn[res.first+n]=max(maxn[res.first+n],{res.second+n,i});
}
else{
maxn[res.first]=max(maxn[res.first],{res.second+n,i});
}
}
vector<int> res;
for(int i=0;i<n;i++){
vector<int> ans;
int lo=i,ro=maxn[i].first;ans.push_back(maxn[i].second);
bool flag=false;
while(lo<=ro){
if(ro>=i+n) {flag=true;break;}
pair<int,int> mq={0,0};
for(int j=lo;j<=ro;j++){
mq=max(mq,maxn[j]);
}
lo=ro+1,ro=mq.first,ans.push_back(mq.second);
}
if(flag&&(res.empty()||res.size()>ans.size())) res=ans;
}
if(res.size()==0) {cout<<"-1\n";return ;}
cout<<res.size()<<'\n';
if(!res.empty()){
int sz=res.size();
for(int j=0;j<sz;j++){
cout<<res[j]<<" \n"[j==sz-1];
}
}
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
cin >> _;
while (_--) solve();
return 0;
}
/*
4 4
0 0
1 0
1 1
0 1
3 3
-1 3
2 3
0 -10
*/
这程序好像有点Bug,我给组数据试试?
詳細信息
Test #1:
score: 100
Accepted
time: 0ms
memory: 3620kb
input:
1 3 3 0 0 1 0 0 1 -1 -1 3 -1 -1 3
output:
2 2 1
result:
ok 1 cases.
Test #2:
score: 0
Accepted
time: 11ms
memory: 3524kb
input:
100 13 17 -976 -766 -628 -956 462 -987 967 -997 981 -123 919 115 847 336 692 789 350 908 -558 996 -843 944 -944 400 -974 -476 -41876798 919231678 -375313647 26070145 -288061228 527643156 -93144407 730297 93699145 -260606010 -393321698 -339399089 644245933 784344503 -731740672 525632046 -32141854 114...
output:
2 16 17 -1 -1 -1 -1 3 17 20 14 -1 4 13 27 3 22 -1 -1 -1 8 19 15 7 3 14 2 10 12 4 6 10 5 7 -1 3 3 2 7 -1 -1 -1 -1 -1 4 8 11 10 21 4 13 3 12 7 4 5 7 1 2 4 17 48 25 13 4 33 22 38 32 5 37 40 22 6 38 37 88 41 72 55 86 6 62 60 63 71 83 26 76 38 51 7 20 84 4 9 12 14 32 45 24 78 68 73 67 23 29 11 48 49 85 7...
result:
ok 100 cases.
Test #3:
score: 0
Accepted
time: 83ms
memory: 3884kb
input:
100 1000 1000 -206566811 272513 -206555115 -2214957 -206550642 -2598812 -206538524 -3429227 -206534118 -3685047 -206497885 -5342748 -206466348 -6447384 -206454728 -6809307 -206416737 -7877319 -206365268 -9126757 -206352649 -9407755 -206350222 -9460834 -206342491 -9627970 -206253359 -11378633 -206140...
output:
-1 106 175 640 460 660 850 722 990 573 214 893 375 983 683 421 276 30 107 95 561 191 564 971 506 118 836 735 822 765 515 499 882 42 818 524 789 443 249 140 451 872 525 422 959 969 147 716 227 928 577 46 194 877 452 980 903 281 714 24 803 612 75 1 957 894 416 895 173 254 970 39 812 958 205 653 912 88...
result:
ok 100 cases.
Test #4:
score: 0
Accepted
time: 156ms
memory: 3696kb
input:
100 1000 1000 -208687104 -518935 -208658071 -3519412 -208647420 -4102540 -208612602 -5599926 -208458791 -9772885 -208145426 -15035235 -207718591 -20088894 -207636408 -20921257 -207598046 -21298548 -207567860 -21590745 -207181177 -25030716 -206899863 -27258453 -206707452 -28681109 -206631693 -2922191...
output:
461 985 29 304 608 501 941 309 656 91 73 712 725 98 245 609 33 81 970 968 593 559 453 882 880 626 357 452 249 455 993 90 956 495 254 197 731 316 854 955 662 340 539 613 927 787 8 664 874 398 142 998 409 670 270 715 136 746 695 668 497 430 217 403 982 436 407 857 373 480 707 717 105 337 822 831 793 5...
result:
ok 100 cases.