• 题解 P4390 【[BOI2007]Mokia 摩基亚】


    这道题我爱了!

    思路

    看到这题目我直接想到了三值偏序,然后我就开始了不归之路

    1.把操作按时间排序,就能离线操作了

    2.首先读入的时候各个操作已经默认是按时间排序的了,所以不用考虑时间这一维

    接着,操作分两种:
    (1).添加住户(相当于是把这个点的权值加上一个a)

    (2).查询住户(查询的这个范围是个矩形)

    所以自然就可以用归并排序+树状数组来解决了

    其中最妙的一步在于将操作2中的给出的两个点进行扩展,扩展成4个点来进行操作,然后在归并排序的时候按照坐标x来排序,根据树状数组的性质来进行操作:

    结合代码来讲一下

    for (;tql!=3;){
        cin>>tql;
        if(tql == 1)R++,T[R].tt=R,cin>>T[R].x>>T[R].y>>T[R].z;
        if(tql == 2){
            R++;
            int m=R;
            book[m]=1;
            R=R,T[R].t=1,cin>>T[R].x>>T[R].y,T[R].tt=m;
            T[R].x--,T[R].y--;
            R++,T[R].t=4,cin>>T[R].x>>T[R].y,T[R].tt=m;
            R++,T[R].t=2,T[R].x=T[R-2].x,T[R].y=T[R-1].y,T[R].tt=m;
            R++,T[R].t=3,T[R].x=T[R-2].x,T[R].y=T[R-3].y,T[R].tt=m;
        }
    

    }

    (见tql==2的情况)

    (给拓展的四个点进行标记然后在后面计算答案)

    if(T[t2].t == 1)tong[T[t2].tt]+=get(T[t2].y);

    if(T[t2].t == 2)tong[T[t2].tt]-=get(T[t2].y);

    if(T[t2].t == 3)tong[T[t2].tt]-=get(T[t2].y);if(T[

    t2].t == 4)tong[T[t2].tt]+=get(T[t2].y);

    此处请自行脑补一个树状数组

    借用前面题解的图片来理解

    CODE

    #include  <bits/stdc++.h>
    using namespace std;
    int c[2005001];
    int tong[200001];
    int w,tql,R=0;
    struct node{int x,y,z,t,tt;}T[200001],p[200001];
    int book[200005];
    int lowbit(int x){return x&(-x);}
    
    int add(int x,int k){
      while(x <= w)c[x]+=k,x+=lowbit(x);
      return 0;
    }
    
    int get(int x){
      int total=0;
      while(x > 0)
      total+=c[x],x-=lowbit(x);
      return total;
    }
    
    int CDQ(int l , int r ){
      if(l == r)return 0;
      int mid=(l+r)>>1;
      CDQ(l,mid);CDQ(mid+1,r);
      int t1=l,t2=mid+1;
      for (int i = l ; i <= r ; i ++){
          if(T[t1].x <= T[t2].x && t1 <=mid || t2 > r){
              if(T[t1].t == 0)add(T[t1].y,T[t1].z);
              p[i]=T[t1],t1++;
          }
          else {
              if(T[t2].t == 1)tong[T[t2].tt]+=get(T[t2].y);
              if(T[t2].t == 2)tong[T[t2].tt]-=get(T[t2].y);
              if(T[t2].t == 3)tong[T[t2].tt]-=get(T[t2].y);
              if(T[t2].t == 4)tong[T[t2].tt]+=get(T[t2].y);
              p[i]=T[t2],t2++;
          }
      }
      for (int i = l ; i <= mid ; i ++)
      if(T[i].t == 0)add(T[i].y,-T[i].z);
      for (int i = l ; i <= r ; i ++)
      T[i]=p[i];
      return 0;
    }
    int main(){
      cin>>tql>>w;
      R=0;
      for (;tql!=3;){
          cin>>tql;
          if(tql == 1)R++,T[R].tt=R,cin>>T[R].x>>T[R].y>>T[R].z;
          if(tql == 2){
              R++;
              int m=R;
              book[m]=1;
              R=R,T[R].t=1,cin>>T[R].x>>T[R].y,T[R].tt=m;
              T[R].x--,T[R].y--;
              R++,T[R].t=4,cin>>T[R].x>>T[R].y,T[R].tt=m;
              R++,T[R].t=2,T[R].x=T[R-2].x,T[R].y=T[R-1].y,T[R].tt=m;
              R++,T[R].t=3,T[R].x=T[R-2].x,T[R].y=T[R-3].y,T[R].tt=m;
          }
          if(tql == 3)break;
      }
      
      CDQ(1,R);
      for (int i = 1 ; i <= R ; i ++)
      if(book[i] != 0)cout<<tong[i]<<endl;
      return 0;
    }
    
  • 相关阅读:
    php下拉选项的批量操作方法
    php(Yii)的增删改查之改
    无限分类方法大全
    Ajax 实例大全
    从入门到精通1
    课后作业二需求分析
    2018年春季个人阅读计划
    软件需求与分析需掌握的内容
    阅读笔记3
    阅读笔记
  • 原文地址:https://www.cnblogs.com/MYCui/p/13869920.html
Copyright © 2020-2023  润新知