zoukankan      html  css  js  c++  java
  • bzoj2639 矩形计算

    https://www.cnblogs.com/ouuan/p/2DMoDui.html

    输入一个n*m的矩阵,矩阵的每一个元素都是一个整数,然后有q个询问,每次询问一个子矩阵的权值。矩阵的权值是这样定义的,对于一个整数x,如果它在该矩阵中出现了p次,那么它给该矩阵的权值就贡献p2。

    Input

    第一行两个整数n,m表示矩阵的规模。
    接下来n行每行m个整数,表示这个矩阵的每个元素。
    再下来一行一个整数q,表示询问个数。
    接下来q行每行四个正整数x1,y1,x2,y2,询问以第x1行第y1列和第x2行第y2列的连线为对角线的子矩阵的权值。
    Output

    输出q行每行一个整数回答对应询问。
    Sample Input

    3 4

    1 3 2 1

    1 3 2 4

    1 2 3 4

    8

    1 2 2 1

    1 1 2 1

    1 1 3 4

    1 1 1 1

    2 2 3 3

    3 4 2 2

    1 3 3 1

    2 4 3 4

    Sample Output

    8

    4

    38

    1

    8

    12

    27

    4

    HINT

    对于全部数据

    1<=n,m<=200

    q<=100000

    |矩阵元素大小|<=2*10^9

    Sol:

    二维莫队

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    
    using namespace std;
    
    const int N=210;
    const int M=100010;
    
    void add(int x);
    void del(int x);
    
    int r,c,m,B,a[N][N],lsh[N*N],tot,cnt[N*N],ans,out[M];
    
    struct Query
    {
    	int x,y,xx,yy,id;
    	bool operator<(Query& b)
    	{
    		return x/B==b.x/B?(y/B==b.y/B?(xx/B==b.xx/B?yy<b.yy:xx<b.xx):y<b.y):x<b.x;
    	}
    } q[M];
    
    int main()
    {
    	int i,j,x=1,y=1,xx=0,yy=0;
    	
    	cin>>r>>c>>m;
    	
    	B=pow(r*c,0.5)/pow(m,0.25)+1.0;
    	
    	for (i=1;i<=r;++i)
    	{
    		for (j=1;j<=c;++j)
    		{
    			cin>>a[i][j];
    			lsh[tot++]=a[i][j]; //这题要离散化
    		}
    	}
    	
    	sort(lsh,lsh+tot);
    	tot=unique(lsh,lsh+tot)-lsh;
    	
    	for (i=1;i<=r;++i)
    	{
    		for (j=1;j<=c;++j)
    		{
    			a[i][j]=lower_bound(lsh,lsh+tot,a[i][j])-lsh;
    		}
    	}
    	
    	for (i=0;i<m;++i)
    	{
    		cin>>q[i].x>>q[i].y>>q[i].xx>>q[i].yy;
    		q[i].id=i;
    	}
    	
    	sort(q,q+m);
    	
    	for (i=0;i<m;++i)
    	{
    		while (x>q[i].x)
    		{
    			--x;
    			for (j=y;j<=yy;++j)
    			{
    				add(a[x][j]);
    			}
    		}
    		while (xx<q[i].xx)
    		{
    			++xx;
    			for (j=y;j<=yy;++j)
    			{
    				add(a[xx][j]);
    			}
    		}
    		while (y>q[i].y)
    		{
    			--y;
    			for (j=x;j<=xx;++j)
    			{
    				add(a[j][y]);
    			}
    		}
    		while (yy<q[i].yy)
    		{
    			++yy;
    			for (j=x;j<=xx;++j)
    			{
    				add(a[j][yy]);
    			}
    		}
    		while (x<q[i].x)
    		{
    			for (j=y;j<=yy;++j)
    			{
    				del(a[x][j]);
    			}
    			++x;
    		}
    		while (xx>q[i].xx)
    		{
    			for (j=y;j<=yy;++j)
    			{
    				del(a[xx][j]);
    			}
    			--xx;
    		}
    		while (y<q[i].y)
    		{
    			for (j=x;j<=xx;++j)
    			{
    				del(a[j][y]);
    			}
    			++y;
    		}
    		while (yy>q[i].yy)
    		{
    			for (j=x;j<=xx;++j)
    			{
    				del(a[j][yy]);
    			}
    			--yy;
    		}
    		out[q[i].id]=ans;
    	}
    	
    	for (i=0;i<m;++i)
    	{
    		cout<<out[i]<<endl;
    	}
    	
    	return 0;
    }
    
    void add(int x)
    {
    	ans=ans+2*cnt[x]+1;
    	++cnt[x];
    }
    
    void del(int x)
    {
    	ans=ans-2*cnt[x]+1;
    	--cnt[x];
    }
    

      

  • 相关阅读:
    Java基础教程:面向对象编程[3]
    Java拓展教程:文件DES加解密
    JavaScript:学习笔记(4)——This关键字
    jQuery:[2]百度地图开发平台实战
    Android开发——减小APK大小
    玩转ButterKnife注入框架
    Java技术——多态的实现原理
    RxAndroid结合Retrofit,看看谁才是最佳拍档!
    Android开发——AsyncTask的使用以及源码解析
    10本比较鸡肋的技术类书籍,简要回顾
  • 原文地址:https://www.cnblogs.com/cutemush/p/12884895.html
Copyright © 2011-2022 走看看