求助
考虑爆炸只会发生在相邻的两个炸弹,那么我们不妨把所有相邻的炸弹的信息放入set,然后每次找到爆炸时间尽可能短的,然后把它们删除,删除以后呢?肯定要把与它两相连的删除掉在set里,然后呢,把爆炸后的左右相连的点合并放入set.就做完了.左右相连用链表维护.
不知道wa在哪里了...求大佬看看
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e5+5; const double eps=1e-3; struct sb{ double w; int ida,idb; }; bool operator<(sb A,sb B) { if(A.w==B.w) { if(A.ida==B.ida) return A.idb<B.idb; else return A.ida<B.ida; } else return A.w<B.w; } int l[N],r[N];//维护这个点左/右边下标是哪个点 bool ans[N]; vector<int>res; struct nm{ double x,v; int id; }b[N]; bool cmp(nm A,nm B) { return A.x<B.x; } double Time(nm A,nm B) { if(A.v>=0&&B.v<0||A.v>0&&B.v<=0) { return (B.x-A.x)/(A.v-B.v); } else if(A.v<=0&&B.v>=0) return 1e9; else { if(A.v<0&&B.v<0&&A.v<=B.v) return 1e9; if(A.v>0&&B.v>0&&A.v<=B.v) return 1e9; double V=fabs(A.v-B.v); if(V<=eps) return 1e9; return (B.x-A.x)/V; } } void merge(int L,int R) { r[L]=R; l[R]=L; } void run() { //set 放三个元素一定是从左往右放 int n; set<sb>s; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lf",&b[i].x); for(int i=1;i<=n;i++) { scanf("%lf",&b[i].v); b[i].id=i; } sort(b+1,b+1+n,cmp); for(int i=1;i<=n;i++) { if(i==1) { l[b[i].id]=0; r[b[i].id]=b[i+1].id; } else if(i==n) { l[b[i].id]=b[i-1].id; r[b[i].id]=n+1; s.insert({Time(b[i-1],b[i]),b[i-1].id,b[i].id}); } else { l[b[i].id]=b[i-1].id; r[b[i].id]=b[i+1].id; s.insert({Time(b[i-1],b[i]),b[i-1].id,b[i].id}); } } for(int i=1;i<=n/2;i++) { auto x=*s.begin(); if(fabs(x.w-1e9)<=eps) break; s.erase(x); if(l[x.ida]!=0) s.erase({Time(b[l[x.ida]],b[x.ida]),l[x.ida],x.ida}); if(r[x.idb]!=n+1) s.erase({Time(b[x.idb],b[r[x.idb]]),x.idb,r[x.idb]}); if(l[x.ida]!=0&&r[x.idb]!=n+1) { s.insert({Time(b[l[x.ida]],b[r[x.idb]]),l[x.ida],r[x.idb]}); } merge(l[x.ida],r[x.idb]); } for(auto x:s) { if(!ans[x.ida]) ans[x.ida]=true,res.push_back(x.ida); if(!ans[x.idb]) ans[x.idb]=true,res.push_back(x.idb); } printf("%d\n",(int)res.size()); sort(res.begin(),res.end()); for(int x:res) { printf("%d\n",x); } } int main() { int T=1; //cin>>T; while(T--) { run(); } return 0; } /* 5 1 3 5 7 9 -1 -2 -4 2 4 */