zoukankan      html  css  js  c++  java
  • [CSP-S模拟测试]:蔬菜(二维莫队)

    题目描述

      小$C$在家中开垦了一块菜地,可以抽象成一个$r imes c$大小的矩形区域,菜地的每个位置都种着一种蔬菜。秋天到了,小$C$家的菜地丰收了。
      小$C$拟定了$q$种采摘蔬菜的计划,计划采摘区域是菜地的一个子矩形,你需要帮助他计算每种计划的美味度,美味度等于每种蔬菜在采摘区域出现次数的平方和。


    输入格式

    第一行三个正整数$r,c,q$。
    接下来$r$行每行$c$个正整数,第$i+1$行第$j$个数为$a_i,j$,表示每个位置的蔬菜种类。
    接下来$q$行,每行$4$个正整数$x_0,y_0,x_1,y_1$表示采摘区域的左上角和右下角的位置。


    输出格式

    输出$q$行,每行一个整数,第$i$行的数表示第$i$组采摘计划的答案。


    样例

    样例输入:

    3 4 8
    1 3 2 1
    1 3 2 4
    1 2 3 4
    1 1 2 2
    1 1 2 1
    1 1 3 4
    1 1 1 1
    2 2 3 3
    2 2 3 4
    1 1 3 3
    2 4 3 4

    样例输出:

    8
    4
    38
    1
    8
    12
    27
    4


    数据范围与提示

    对于$100\%$的数据,$r,cleqslant 200,qleqslant 100,000,a_i,jleqslant {10}^9$。
    $ullet Subtask 1(23pts):r,cleqslant 100,qleqslant 1,000$。
    $ullet Subtask 2(15pts):r,cleqslant 100,qleqslant 10,000$。
    $ullet Subtask 3(17pts):r,cleqslant 200,qleqslant 50,000$。
    $ullet Subtask 4(20pts):$蔬菜种类数不超过$200$。
    $ullet Subtask 5(25pts):$无特殊限制


    题解

    正解是四维偏序,说白了就是$CDQ$套$CDQ$。

    然而可以用二维莫队水,队爷就是$NB$。

    推销一波二维莫队:二维莫队(离线)

    对于可怕的数据范围,直接离散化搞就好了。

    说了二维莫队就没啥好说的了,在这里就想再说三点:

      $alpha.$对于一个知识点,你比别人多学或者是早学不是错;哪怕你是知道这次要考什么,因为即便告诉别人用什么解法,不会还是不会;而对于有人说的认为复杂度不对,也可以归结为不会——$to$可爱的同桌。

      $eta.$这道题的数据有点水,所以打一个假的二维莫队也可以水过去,有的人知道,有的人不知道,在此提醒一下,这样排序是不对的:

    bool cmp(rec a,rec b){return (a.x0==b.x0)?((a.x2==b.x2)?((a.y0==b.y0)?a.y2<b.y2:a.y0<b.y0):a.x2<b.x2):a.x0<b.x0;}
    

      但是的确可以水过去,正确的方法应该是:

    int sqrr=sqrt(r);sqrc=sqrt(c);
    bool cmp(rec a,rec b){return a.x0/sqrr==b.x0/sqrr?(a.y0/sqrc==b.y0/sqrc?(a.x2/sqrr==b.x2/sqrr?a.y2/sqrc<b.y2/sqrc:a.x2<b.x2):a.y0<b.y0):a.x0<b.x0;}
    

      $gamma.$最好利用公式统计答案,即${x+1)}^2-x^2$,因为在种类过多的时候肯定会卡死的。

    时间复杂度:$Theta(qlog q+q imes nsqrt{n})$。

    期望得分:$100$分。

    实际得分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    struct rec{int x0,y0,x2,y2,pos,id;}e[100001];
    int r,c,q;
    int sqrr,sqrc;
    int Map[201][201],zls;
    int s[40001];
    map<int,int> mp;
    long long ans[100001];
    int uu,dd,ll,rr;
    bool cmp(rec a,rec b){return a.x0/sqrr==b.x0/sqrr?(a.y0/sqrc==b.y0/sqrc?(a.x2/sqrr==b.x2/sqrr?a.y2/sqrc<b.y2/sqrc:a.x2<b.x2):a.y0<b.y0):a.x0<b.x0;}
    int ask(int x){return 2*x+1;}
    void upd(int id,int l,int r,bool b,bool w){for(int i=l;i<=r;i++)if(b)if(w){ans[0]+=ask(s[Map[id][i]]);s[Map[id][i]]++;}else{s[Map[id][i]]--;ans[0]-=ask(s[Map[id][i]]);}else if(w){ans[0]+=ask(s[Map[i][id]]);s[Map[i][id]]++;}else{s[Map[i][id]]--;ans[0]-=ask(s[Map[i][id]]);}}
    int main()
    {
    	scanf("%d%d%d",&r,&c,&q);
    	sqrr=sqrt(r);sqrc=sqrt(c);
    	for(int i=1;i<=r;i++)
    		for(int j=1;j<=c;j++)
    		{
    			scanf("%d",&Map[i][j]);
    			if(!mp[Map[i][j]])Map[i][j]=mp[Map[i][j]]=++zls;
    			else Map[i][j]=mp[Map[i][j]];
    		}
    	for(int i=1;i<=q;i++)
    	{
    		scanf("%d%d%d%d",&e[i].x0,&e[i].y0,&e[i].x2,&e[i].y2);
    		e[i].id=i;
    	}
    	sort(e+1,e+q+1,cmp);
    	ll=rr=e[1].x0;
    	uu=dd=e[1].y0;
    	s[Map[ll][uu]]++;
    	ans[0]=1;
    	for(int i=1;i<=q;i++)
    	{
    		while(uu>e[i].y0)upd(--uu,ll,rr,0,1);
    		while(uu<e[i].y0)upd(uu++,ll,rr,0,0);
    		while(dd<e[i].y2)upd(++dd,ll,rr,0,1);
    		while(dd>e[i].y2)upd(dd--,ll,rr,0,0);
    		while(ll>e[i].x0)upd(--ll,uu,dd,1,1);
    		while(ll<e[i].x0)upd(ll++,uu,dd,1,0);
    		while(rr<e[i].x2)upd(++rr,uu,dd,1,1);
    		while(rr>e[i].x2)upd(rr--,uu,dd,1,0);
    		ans[e[i].id]=ans[0];
    	}
    	for(int i=1;i<=q;i++)printf("%lld
    ",ans[i]);
    	return 0;
    }
    

    rp++

  • 相关阅读:
    URAL 2067 Friends and Berries (推理,数学)
    URAL 2070 Interesting Numbers (找规律)
    URAL 2073 Log Files (模拟)
    URAL 2069 Hard Rock (最短路)
    URAL 2068 Game of Nuts (博弈)
    URAL 2066 Simple Expression (水题,暴力)
    URAL 2065 Different Sums (找规律)
    UVa 1640 The Counting Problem (数学,区间计数)
    UVa 1630 Folding (区间DP)
    UVa 1629 Cake slicing (记忆化搜索)
  • 原文地址:https://www.cnblogs.com/wzc521/p/11577220.html
Copyright © 2011-2022 走看看