思路
①题中I的值不超过1e9,a的值处于0.2—0.8,经计算可得知最多折射100次左右,I就会小于0,从而停止移动。
②题中所有反射面横纵坐标总长都不超过3e5,所以我们可以轻松记录下来反射面的每一个点。
③时间限制为2s,由上可以猜测时间复杂度为100 * 3e5 = 3e7,最多再多一个log。
我们可以将每一个反射面的坐标都分类放入vector中,并将横纵坐标分开存储,将相同横坐标的反射点放入同一个vector,纵坐标同理,某个横坐标的vector每次放的时候都要保证纵坐标从小到大的顺序,方便之后的二分查找。
删除的操作即为将该反射面上的所有点在其横纵坐标vector中都删除掉,用二分可轻松做到。
查询操作即为每次反射都二分查找离自己最近的x坐标或y坐标,具体根据光线的方向而定,然后将光线出发点定为该坐标,进行下一轮操作,直到t为0或I小于1。
时间复杂度为1e8级别。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
typedef pair<int,int> PII;
struct gx{
int dot,kind;
double a;
bool operator < (const gx & W) const {
return a < W.a;
}
};
unordered_map<int,vector<gx> > mpx;
unordered_map<int,vector<gx> > mpy;
int m;
struct opera{
int x1,y1,x2,y2;
double a;
}ope[N];
int find(vector<gx> &s,int x){
int l = 0,r = s.size() - 1;
while(l <= r){
int mid = l + r >> 1;
//cout << s[mid].dot << " # " << x << endl;
if(s[mid].dot <= x) l = mid + 1;
else r = mid - 1;
}
return l;
}
int find2(vector<gx> &s,int x){
int l = 0,r = s.size() - 1;
while(l <= r){
int mid = l + r >> 1;
//cout << s[mid].dot << " # " << x << endl;
if(s[mid].dot >= x) r = mid - 1;
else l = mid + 1;
}
return r;
}
void inst(vector<gx> &s,gx p){
int x = p.dot;
int idx = find2(s,x);
s.insert(s.begin() + idx + 1,p);
}
int main(){
cin >> m;
for(int ll = 1;ll <= m;ll ++){
int op;
scanf("%d",&op);
if(op == 1){
int x1,y1,x2,y2;
double a;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
scanf("%lf",&a);
if(abs(x1 - x2) <= 1 || abs(y1 - y2) <= 1){
ope[ll] = {-1,-1,-1,-1,-1};
continue;
}
int xx1,yy1,xx2,yy2;
xx1 = x1,yy1 = y1,xx2 = x2,yy2 = y2;
if(x1 < x2)
x1 ++,x2 --;
else
x1 --,x2 ++;
if(y1 < y2)
y1 ++,y2 --;
else
y1 --,y2 ++;
ope[ll] = {xx1,yy1,xx2,yy2,a};
if((yy2 - yy1) / (xx2 - xx1) > 0){
if(x1 > x2){
swap(x1,x2),swap(y1,y2);
}
for(int i = 0;i <= x2 - x1;i ++){
int x = x1 + i,y = y1 + i;
inst(mpx[x],{y,1,a});
inst(mpy[y],{x,1,a});
}
}
else{
if(x1 > x2){
swap(x1,x2),swap(y1,y2);
}
for(int i = 0;i <= x2 - x1;i ++){
int x = x1 + i,y = y1 - i;
inst(mpx[x],{y,-1,a});
inst(mpy[y],{x,-1,a});
}
}
}
else if(op == 2){
int k;
scanf("%d",&k);
int x1,y1,x2,y2;
double a;
x1 = ope[k].x1,y1 = ope[k].y1,x2 = ope[k].x2,y2 = ope[k].y2;
a = ope[k].a;
if(a == -1) continue;
int xx1,yy1,xx2,yy2;
xx1 = x1,yy1 = y1,xx2 = x2,yy2 = y2;
if(x1 < x2)
x1 ++,x2 --;
else
x1 --,x2 ++;
if(y1 < y2)
y1 ++,y2 --;
else
y1 --,y2 ++;
if((yy2 - yy1) / (xx2 - xx1) > 0){
if(x1 > x2){
swap(x1,x2),swap(y1,y2);
}
for(int i = 0;i <= x2 - x1;i ++){
int x = x1 + i,y = y1 + i;
vector<gx> ax = mpx[x];
vector<gx> ay = mpy[y];
int it = find2(ax,y1 + i);
ax.erase(ax.begin() + it + 1);
mpx[x] = ax;
it = find2(ay,x1 + i);
ay.erase(ay.begin() + it + 1);
mpy[y] = ay;
}
}
else{
if(x1 > x2){
swap(x1,x2),swap(y1,y2);
}
for(int i = 0;i <= x2 - x1;i ++){
int x = x1 + i,y = y1 - i;
vector<gx> ax = mpx[x];
vector<gx> ay = mpy[y];
int it = find2(ax,y1 - i);
ax.erase(ax.begin() + it + 1);
mpx[x] = ax;
it = find2(ay,x);
ay.erase(ay.begin() + it + 1);
mpy[y] = ay;
}
}
}
else{
int x,y,d,t;
double I;
scanf("%d%d%d%lf%d",&x,&y,&d,&I,&t);
while(1){
//printf("I:%lf,t:%d,x:%d,y:%d,d:%d\n",I,t,x,y,d);
if(I < 1 || t == 0) break;
if(d == 0){
vector<gx> ay = mpy[y];
int idx = find(ay,x);
if(idx == ay.size()){
if(d == 0)
x += t;
else if(d == 1)
y += t;
else if(d == 2)
x -= t;
else
y -= t;
t = 0;
break;
}
gx it = ay[idx];
int c = min(t,(it.dot - x));
if(t >= it.dot - x)
I *= it.a;
x += c;
t -= c;
if(it.kind == 1)
d = 1;
else
d = 3;
}
else if(d == 2){
vector<gx> ay = mpy[y];
int idx = find2(ay,x);
if(idx < 0){
if(d == 0)
x += t;
else if(d == 1)
y += t;
else if(d == 2)
x -= t;
else
y -= t;
t = 0;
break;
}
gx it = ay[idx];
int c = min(t,(x - it.dot));
if(t >= x - it.dot)
I *= it.a;
x -= c;
t -= c;
if(it.kind == 1)
d = 3;
else
d = 1;
}
else if(d == 1){
vector<gx> ax = mpx[x];
int idx = find(ax,y);
if(idx == ax.size()){
if(d == 0)
x += t;
else if(d == 1)
y += t;
else if(d == 2)
x -= t;
else
y -= t;
t = 0;
break;
}
gx it = ax[idx];
int c = min(t,(it.dot - y));
if(t >= it.dot - y)
I *= it.a;
y += c;
t -= c;
if(it.kind == 1)
d = 0;
else
d = 2;
}
else{
vector<gx> ax = mpx[x];
int idx = find2(ax,y);
if(idx < 0){
if(d == 0)
x += t;
else if(d == 1)
y += t;
else if(d == 2)
x -= t;
else
y -= t;
t = 0;
break;
}
gx it = ax[idx];
// for(auto p : ax){
// cout << p.dot << " " << p.a << "#" <<endl;
// }
int c = min(t,(y - it.dot));
if(t >= y - it.dot)
I *= it.a;
y -= c;
t -= c;
if(it.kind == 1)
d = 2;
else
d = 0;
}
}
if(I < 1){
printf("0 0 0\n");
}
else{
printf("%d %d %d\n",x,y,(int)I);
}
}
}
return 0;
}
orz,太强了
orz,超级大佬
orz,太强了
orz
,偶遇大佬