zoukankan      html  css  js  c++  java
  • BZOJ 1176: [Balkan2007]Mokia

    BZOJ 1176: [Balkan2007]Mokia

    标签(空格分隔): OI BZOJ cdq分治 分治 树状数组


    Time Limit: 30 Sec
    Memory Limit: 162 MB


    Description

    维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000.

    Input

    第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小

    接下来每行为一下三种输入之一(不包含引号):

    "1 x y a"

    "2 x1 y1 x2 y2"

    "3"

    输入1:你需要把(x,y)(第x行第y列)的格子权值增加a

    输入2:你需要求出以左上角为(x1,y1),右下角为(x2,y2)的矩阵内所有格子的权值和,并输出

    输入3:表示输入结束

    Output

    对于每个输入2,输出一行,即输入2的答案

    Sample Input

    0 4

    1 2 3 3

    2 1 1 3 3

    1 2 2 2

    2 2 2 3 4

    3
    Sample Output

    3

    5
    HINT

    保证答案不会超过int范围


    Solution####

    cdq分治+树状数组 (O(n*log_2n))。2008年cdq的国家集训队作业有相关资料


    Code####

    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<map>
    #include<bitset>
    #include<vector>
    using namespace std;
    #define PA pair<int,int>
    const int N=0,M=0;
    int read()
    {int s=0,f=1;char ch=getchar();
     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-'0';ch=getchar();}
     return s*f;
    }
    //smile please
    int n,T,m;
    struct que
    {
    	bool ask;int x,y,s,t,h;
    }q[800005];int qs;
    bool operator<(que a,que b)
    {
    	return a.x<b.x||(a.x==b.x&&a.ask<b.ask);
    }
    int s[2000005];
    que *a[800005];
    que *aa[800005];
    int ans[200005];
    void gb(int l,int r)
    {
    	int mid=l+r>>1;
    	int i=l,j=mid+1,k=l;
    	for(int i=l;i<=r;i++)
    	   aa[i]=a[i];
    	while(i!=mid+1||j!=r+1)
    	  {if(i==mid+1)a[k++]=aa[j++];
    	   else if(j==r+1)a[k++]=aa[i++];
    	   else if(*aa[i]<*aa[j])a[k++]=aa[i++];
    	   else a[k++]=aa[j++];
    	  }
    }
    void cdq(int l,int r)
    {
    	if(l==r)return;
    	int mid=l+r>>1;
    	cdq(l,mid);cdq(mid+1,r);
    	gb(l,r);
    	for(int i=l;i<=r;i++)
    	   {que now=*a[i];
    	    if(now.ask)
    	     {if(now.h<=mid)continue;
    	      int sum=0;
    		  for(int x=now.y;x;x-=x&-x)
    	         sum+=s[x];
    	      ans[now.t]+=sum*now.s;
    		 }
    	   else
    	     {if(now.h>mid)continue;
    	      for(int x=now.y;x<=n;x+=x&-x)
    	         s[x]+=now.s;
    		 }
    	   }
    	for(int i=l;i<=r;i++)
    	   {que now=*a[i];
    	    if(!now.ask)
    	      {if(now.h>mid)continue;
    	       for(int x=now.y;x<=n;x+=x&-x)
    	          s[x]=0;
    		  }
    	   }
    }
    int main()
    {
    	m=read();n=read();T=1;
    	for(int op=read();op!=3;op=read(),++T)
    	    if(op==1)
    	      q[++qs]=(que){0,read(),read(),read(),T,qs},ans[T]=-1;
    		else
    		  {int x1=read(),y1=read(),x2=read(),y2=read();
    		   q[++qs]=(que){1,x2,y2,1,T,qs};
    		   q[++qs]=(que){1,x2,y1-1,-1,T,qs};
    		   q[++qs]=(que){1,x1-1,y2,-1,T,qs};
    		   q[++qs]=(que){1,x1-1,y1-1,1,T,qs};
    		   ans[T]+=(x2-x1)*(y2-y1)*m;
    		  }
    	for(int i=1;i<=qs;i++)a[i]=&q[i];
    	cdq(1,qs);
    	for(int i=1;i<T;i++)
    	   if(ans[i]!=-1)
    	     printf("%d
    ",ans[i]);
    	return 0;
    }
    
    
  • 相关阅读:
    编写Music类
    Double-checked locking and the Singleton pattern--双重检查加锁失效原因剖析
    C语言中,数组名作为参数传递给函数时,退化为指针
    蘑菇街笔试
    动态规划--股市买入卖出时间点选择问题
    Java 查看死锁的方法
    linux中shell变量$#,$@,$0,$1,$2的含义解释
    Spring中bean的配置
    为什么要使用连接池
    Hadoop Bloom filter应用示例
  • 原文地址:https://www.cnblogs.com/wuyuhan/p/5238756.html
Copyright © 2011-2022 走看看