版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/XLno_name/article/details/83016939
题意:
数据范围:
时限6S
Analysis:
假设我们已知哪些格子不能走,且仅有第二个操作怎么做?可以用类似
旅行者的分治最短路的方式去做。那么这题我们格子是会发生变化的,需要实时知道信息。但我们可以知道每个格子变为不能走的时间,那么定义这个时间为这个格子的权值,一条路径的权值为这条路径上格子权值最小值。显然对于一个询问
,我们就需要找一条权值最大的路径,看这个权值是否大于该询问的时间。对于询问和修改离线下来,先整体二分出每个格子变不能走的时间,然后用类似
旅行者的分治
去解决询问就好了。
复杂度:
Code:
# include<cstdio>
# include<cstring>
# include<algorithm>
using namespace std;
# define id(x,y) ((x) - 1) * m + (y)
const int N = 2e5 + 5;
typedef long long ll;
struct node
{
int x,l,r,v,id;
}q[N << 1],a[N << 1],b[N << 1],z[N];
ll t[N];
int ti[N],ans[N],f[N],lim[N],g[N];
int n,m,L,Q,h,h1;
inline int read()
{
int x = 0; char ch = getchar();
for (; ch < '0' || ch > '9' ; ch = getchar());
for (; ch >= '0' && ch <= '9' ; ch = getchar()) x = x * 10 + ch - '0';
return x;
}
bool cmp(node a,node b) { return a.x == b.x ? a.id > b.id : a.x < b.x; }
inline void add(int x,int w)
{ for (int i = x ; i <= m ; i += i & (-i)) t[i] += w; }
inline ll qry(int x)
{
ll ret = 0;
for (int i = x ; i ; i -= i & (-i)) ret += t[i];
return ret;
}
inline void divi(int l,int r,int ql,int qr)
{
if (ql > qr) return;
if (l == r)
{
for (int i = ql ; i <= qr ; ++i)
if (!q[i].id) ti[id(q[i].x,q[i].l)] = l;
return;
}
int mid = (l + r) >> 1,h = 0,h1 = 0;
sort(q + ql,q + qr + 1,cmp);
for (int i = ql ; i <= qr ; ++i)
{
if (q[i].id)
{
if (q[i].id <= mid) add(q[i].l,q[i].v),add(q[i].r + 1,-q[i].v),a[++h] = q[i];
else b[++h1] = q[i];
}else
{
if (qry(q[i].l) + q[i].v >= L) a[++h] = q[i];
else q[i].v += qry(q[i].l),b[++h1] = q[i];
}
}
for (int i = ql ; i <= ql + h - 1 ; ++i) q[i] = a[i - ql + 1];
for (int i = qr ; i >= qr - h1 + 1 ; --i) q[i] = b[qr - i + 1];
divi(l,mid,ql,ql + h - 1),divi(mid + 1,r,qr - h1 + 1,qr);
}
inline void calc(int x,int y,int x1,int y1,int opt)
{
if (opt == 1)
{
for (int i = x1 ; i >= x ; --i)
for (int j = y1 ; j >= y ; --j)
{
f[id(i,j)] = f[id(i + 1,j)];
if (j + 1 <= y1) f[id(i,j)] = max(f[id(i,j)],f[id(i,j + 1)]);
f[id(i,j)] = min(ti[id(i,j)],f[id(i,j)]);
}
}else if (opt == 2)
{
for (int i = x ; i <= x1 ; ++i)
for (int j = y ; j <= y1 ; ++j)
{
f[id(i,j)] = f[id(i - 1,j)];
if (j - 1 >= y) f[id(i,j)] = max(f[id(i,j)],f[id(i,j - 1)]);
f[id(i,j)] = min(ti[id(i,j)],f[id(i,j)]);
}
}else if (opt == 3)
{
for (int j = y1 ; j >= y ; --j)
for (int i = x1 ; i >= x ; --i)
{
f[id(i,j)] = f[id(i,j + 1)];
if (i + 1 <= x1) f[id(i,j)] = max(f[id(i,j)],f[id(i + 1,j)]);
f[id(i,j)] = min(ti[id(i,j)],f[id(i,j)]);
}
}else if (opt == 4)
{
for (int j = y ; j <= y1 ; ++j)
for (int i = x ; i <= x1 ; ++i)
{
f[id(i,j)] = f[id(i,j - 1)];
if (i - 1 >= x) f[id(i,j)] = max(f[id(i,j)],f[id(i - 1,j)]);
f[id(i,j)] = min(ti[id(i,j)],f[id(i,j)]);
}
}
}
inline void solve(int x,int y,int x1,int y1,int l,int r)
{
if (l > r || x > x1 || y > y1) return;
if (x1 - x > y1 - y)
{
int mid = (x + x1) >> 1,h = 0,h1 = 0;
for (int i = l ; i <= r ; ++i)
if (z[i].x < mid && z[i].r < mid) a[++h] = z[i];
else if (z[i].x > mid && z[i].r > mid) b[++h1] = z[i];
for (int i = y ; i <= y1 ; ++i)
{
f[id(mid,i)] = ti[id(mid,i)];
for (int j = i - 1 ; j >= y ; --j) f[id(mid,j)] = min(ti[id(mid,j)],f[id(mid,j + 1)]);
for (int j = i + 1 ; j <= y1 ; ++j) f[id(mid,j)] = 0;
calc(x,y,mid - 1,y1,1);
for (int j = i - 1 ; j >= y ; --j) g[j] = f[id(mid,j)],f[id(mid,j)] = 0;
for (int j = i + 1 ; j <= y1 ; ++j) f[id(mid,j)] = min(ti[id(mid,j)],f[id(mid,j - 1)]);
calc(mid + 1,y,x1,y1,2);
for (int j = i - 1 ; j >= y ; --j) f[id(mid,j)] = g[j];
for (int j = l ; j <= r ; ++j)
if (z[j].x <= mid && z[j].r >= mid) ans[z[j].id] = max(ans[z[j].id],min(f[id(z[j].x,z[j].l)],f[id(z[j].r,z[j].v)]));
}
for (int i = l ; i <= l + h - 1 ; ++i) z[i] = a[i - l + 1];
for (int i = r ; i >= r - h1 + 1 ; --i) z[i] = b[r - i + 1];
solve(x,y,mid - 1,y1,l,l + h - 1);
solve(mid + 1,y,x1,y1,r - h1 + 1,r);
}else
{
int mid = (y + y1) >> 1,h = 0,h1 = 0;
for (int i = l ; i <= r ; ++i)
if (z[i].l < mid && z[i].v < mid) a[++h] = z[i];
else if (z[i].l > mid && z[i].v > mid) b[++h1] = z[i];
for (int i = x ; i <= x1 ; ++i)
{
f[id(i,mid)] = ti[id(i,mid)];
for (int j = i - 1 ; j >= x ; --j) f[id(j,mid)] = min(ti[id(j,mid)],f[id(j + 1,mid)]);
for (int j = i + 1 ; j <= x1 ; ++j) f[id(j,mid)] = 0;
calc(x,y,x1,mid - 1,3);
for (int j = i - 1 ; j >= x ; --j) g[j] = f[id(j,mid)],f[id(j,mid)] = 0;
for (int j = i + 1 ; j <= x1 ; ++j) f[id(j,mid)] = min(ti[id(j,mid)],f[id(j - 1,mid)]);
calc(x,mid + 1,x1,y1,4);
for (int j = i - 1 ; j >= x ; --j) f[id(j,mid)] = g[j];
for (int j = l ; j <= r ; ++j)
if (z[j].l <= mid && z[j].v >= mid) ans[z[j].id] = max(ans[z[j].id],min(f[id(z[j].x,z[j].l)],f[id(z[j].r,z[j].v)]));
}
for (int i = l ; i <= l + h - 1 ; ++i) z[i] = a[i - l + 1];
for (int i = r ; i >= r - h1 + 1 ; --i) z[i] = b[r - i + 1];
solve(x,y,x1,mid - 1,l,l + h - 1);
solve(x,mid + 1,x1,y1,r - h1 + 1,r);
}
}
int main()
{
freopen("grid.in","r",stdin);
freopen("grid.out","w",stdout);
n = read(),m = read(),L = read(),Q = read();
for (int i = 1 ; i <= Q ; ++i)
{
int opt = read();
if (opt == 1)
{
q[++h].x = read(),q[h].l = q[h + 1].l = read();
q[++h].x = read() + 1,q[h].r = q[h - 1].r = read();
q[h - 1].v = read(),q[h].v = -q[h - 1].v,q[h].id = q[h - 1].id = i;
}else z[++h1].x = read(),z[h1].l = read(),z[h1].r = read(),z[h1].v = read(),z[h1].id = h1,lim[h1] = i;
}
for (int i = 1 ; i <= n ; ++i)
for (int j = 1 ; j <= m ; ++j) q[++h] = (node){i,j,0,0,0};
divi(1,Q,1,h);
solve(1,1,n,m,1,h1);
for (int i = 1 ; i <= h1 ; ++i)
if (ans[i] < lim[i]) puts("no");
else puts("yes");
return 0;
}