[BOI2007]Mokia 摩基亚

嘟嘟嘟


第一反应是二维树状数组,但是看数据范围就果断放弃了。
不过这题刚好符合了修改互不干扰,可离线的标准,因此(CDQ)分治应该可解。
其实这题跟陌上花开很像,只不过第一维是时间,然后第二维是(x),最后一维(y)用树状数组排序。
接下来是重点:
题解的方法是维护二维前缀和,也就是把这个矩形拆成四个点,分别是((x_1 - 1, y_1 - 1)), ((x_1 - 1, y_2)), ((x_2, y_1 - 1)), ((x_2, y_2))。然后就是正常树状数组维护了。
而我的做法是把这个矩形拆成两条线,即左边的边和右边的边,维护的时候是利用(y)的前缀和相减得到区间和。看起来十分有道理,但就是(50)分怎么也(AC)不了。直到最后快疯了才不得不放弃。
这两个代码我都放上去吧

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("") 
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define rg register
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 2e5 + 5;
const int maxm = 2e6 + 5;
inline ll read()
{
  ll ans = 0;
  char ch = getchar(), last = ' ';
  while(!isdigit(ch)) last = ch, ch = getchar();
  while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
  if(last == '-') ans = -ans;
  return ans;
}
inline void write(ll x)
{
  if(x < 0) x = -x, putchar('-');
  if(x >= 10) write(x / 10);
  putchar(x % 10 + '0');
}

int n, m, cnt = 0;

struct Node
{
  int x, y, id, w;
  ll ans;
  bool operator < (const Node& oth)const
  {
    return id < oth.id;
  }
}t[maxn], a[maxn];

ll c[maxm];
int lowbit(int x)
{
  return x & -x;
}
void erase(int pos)
{
  for(; pos <= m; pos += lowbit(pos))
    if(c[pos] != 0) c[pos] = 0;
    else break;
}
void add(int pos, int d)
{
  for(; pos <= m; pos += lowbit(pos)) c[pos] += d;
}
ll query(int pos)
{
  ll ret = 0;
  for(; pos; pos -= lowbit(pos)) ret += c[pos];
  return ret;
}

ll ans[maxn];
int st[maxn], top = 0;
void cdqSolve(int L, int R)
{
  if(L == R) return;
  int mid = (L + R) >> 1, id1 = L, id2 = mid + 1;
  cdqSolve(L, mid); cdqSolve(mid + 1, R);
  for(int i = L; i <= R; ++i)
    {
      if(id2 > R || (id1 <= mid && a[id1].x <= a[id2].x))
	{
	  t[i] = a[id1++];
	  if(!t[i].id) add(t[i].y, t[i].w);
	}
      else
	{
	  t[i] = a[id2++];
	  if(t[i].id) t[i].ans += query(t[i].y);
	}
    }
  for(int i = L; i <= mid; ++i) if(!a[i].id) erase(a[i].y);
  for(int i = L; i <= R; ++i) a[i] = t[i];
}

int main()
{
  scanf("0 %d", &m);
  int op;
  while(scanf("%d", &op) && op != 3)
    {
      if(op == 1)
	{
	  int x = read(), y = read(), w = read();
	  a[++n] = (Node){x, y, 0, w, 0};
	}
      else if(op == 2)
	{
	  int xa = read(), ya = read(), xb = read(), yb = read();
	  a[++n] = (Node){xa - 1, ya - 1, n, 0, 0};
	  a[++n] = (Node){xa - 1, yb, n, 0, 0};
	  a[++n] = (Node){xb, ya - 1, n, 0, 0};
	  a[++n] = (Node){xb, yb, n, 0, 0};
	}
    }
  cdqSolve(1, n);
  sort(a + 1, a + n + 1);
  for(int i = 1; i <= n; ++i)
    if(a[i].id)
      {
	write(a[i + 3].ans - a[i + 1].ans - a[i + 2].ans + a[i].ans), enter;
	i += 3;
      }
  return 0;
}

然后是我的神一般的$50$分代码。 ```c++ #include #include #include #include #include #include #include #include #include #include using namespace std; #define enter puts("") #define space putchar(' ') #define Mem(a, x) memset(a, x, sizeof(a)) #define rg register typedef long long ll; typedef double db; const int INF = 0x3f3f3f3f; const db eps = 1e-8; const int maxn = 2e5 + 5; const int maxm = 2e6 + 5; inline ll read() { ll ans = 0; char ch = getchar(), last = ' '; while(!isdigit(ch)) last = ch, ch = getchar(); while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar(); if(last == '-') ans = -ans; return ans; } inline void write(ll x) { if(x < 0) x = -x, putchar('-'); if(x >= 10) write(x / 10); putchar(x % 10 + '0'); }

int n, m, s, cnt = 0;

struct Node
{
int x, y1, y2, id; bool flg1, flg2; //flg1:query or update flg2:square start or end
bool operator < (const Node& oth)const
{
if(x != oth.x) return x < oth.x;
if(flg1 != oth.flg1)
{
if(flg1 == 1) return oth.flg2 == 1;
else return flg2 == 0;
}
return 1;
}
}t[maxn], a[maxn];

ll c[maxm];
int lowbit(int x)
{
return x & -x;
}
void erase(int pos)
{
for(; pos <= m; pos += lowbit(pos))
if(c[pos] != 0) c[pos] = 0;
else break;
}
void add(int pos, int d)
{
for(; pos <= m; pos += lowbit(pos)) c[pos] += d;
}
ll query(int pos)
{
ll ret = 0;
for(; pos; pos -= lowbit(pos)) ret += c[pos];
return ret;
}

ll ans[maxn];
int st[maxn], top = 0;
void cdqSolve(int L, int R)
{
if(L == R) return;
int mid = (L + R) >> 1, id1 = L, id2 = mid + 1;
cdqSolve(L, mid); cdqSolve(mid + 1, R);
for(int i = L; i <= R; ++i)
{
if(id2 > R || (id1 <= mid && a[id1] < a[id2]))
{
t[i] = a[id1++];
if(t[i].flg1)
{
st[++top] = i;
add(t[i].y1, t[i].y2);
}
}
else
{
t[i] = a[id2++];
if(!t[i].flg1)
{
ll sum = query(t[i].y2) - query(t[i].y1 - 1);
if(!t[i].flg2) ans[t[i].id] -= sum;
else ans[t[i].id] += sum;
}
}
}
for(int i = L; i <= R; ++i) a[i] = t[i];
for(int i = 1; i <= top; ++i) erase(t[st[i]].y1);
top = 0;
}

int main()
{
s = read(); m = read();
int op;
while(scanf("%d", &op) && op != 3)
{
if(op == 1)
{
int x = read(), y = read(), w = read();
a[++n] = (Node){x, y, w, 0, 1, 0};
}
else if(op == 2)
{
int xa = read(), ya = read(), xb = read(), yb = read();
a[++n] = (Node){xa, ya, yb, ++cnt, 0, 0};
a[++n] = (Node){xb, ya, yb, cnt, 0, 1};
ans[cnt] += (ll)(xb - xa + 1) * (ll)(yb - ya + 1) * s;
}
}
cdqSolve(1, n);
for(int i = 1; i <= cnt; ++i) write(ans[i]), enter;
return 0;
}

原文地址:https://www.cnblogs.com/mrclr/p/10040421.html