QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#697145#7015. Rikka with Illuminationspengpeng_fudanWA 10ms3640kbC++239.7kb2024-11-01 11:16:102024-11-01 11:16:11

Judging History

你现在查看的是最新测评结果

  • [2024-11-01 11:16:11]
  • 评测
  • 测评结果:WA
  • 用时:10ms
  • 内存:3640kb
  • [2024-11-01 11:16:10]
  • 提交

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;
    bool flag=(((hull[1]-v)^(hull[0]-v))>=0);
    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)    swap(lcut,rcut);
    lo=lcut.first,ro=lcut.second;
    while(lo<ro){
        int mid=(lo+ro)>>1;
        if(((hull[mid+1]-hull[mid])^(hull[mid+1]-v))<=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+1]-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);
        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(lo>=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;
    }
    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;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 0ms
memory: 3612kb

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: -100
Wrong Answer
time: 10ms
memory: 3640kb

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:

1
0
1
0
0
0
0
1
0
0
1
0
0
0
0
0
0
0
0
0
0
0
0
0
1
0
0
1
0
0
1
0
0
0
0
0
0
0
1
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
0
1
0
0
0
0
0
0
0
0

result:

wrong answer Integer 0 violates the range [1, 17]