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;
    }
    
    
  • 相关阅读:
    【LeetCode OJ】Remove Element
    【LeetCode OJ】Remove Duplicates from Sorted Array
    【LeetCode OJ】Swap Nodes in Pairs
    【LeetCode OJ】Merge Two Sorted Lists
    【LeetCode OJ】Remove Nth Node From End of List
    【LeetCode OJ】Two Sum
    【LeetCode OJ】Majority Element
    最长公共子序列问题
    php fopen与file_get_contents的区别
    PHP 技巧集合
  • 原文地址:https://www.cnblogs.com/wuyuhan/p/5238756.html
Copyright © 2011-2022 走看看