JZOJ5890.【NOIP2018模擬9.29】方格問題
阿新 • • 發佈:2018-11-05
題意:
資料範圍:
時限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;
}