zoukankan      html  css  js  c++  java
  • [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;
    }

  • 相关阅读:
    centos 挂载u盘
    如何将网站部署到tomcat根目录下
    seo工具
    mysql 1045 access denied for user********
    div 自适应宽度
    mysql 日志提示 is marked as crashed and should be repaired
    css overflow:hidden无效解决办法
    java 调用 .net webservice
    Java开发笔记(十五)短路逻辑运算的优势
    Java开发笔记(十四)几种运算符的优先级顺序
  • 原文地址:https://www.cnblogs.com/mrclr/p/10040421.html
Copyright © 2011-2022 走看看