• JZOJ4808. 【NOIP2016提高A组五校联考3】书稿


    Description

    在这里插入图片描述

    • W*H ≤ 2500000 , N,Q ≤ 200000

    Solution

    • 不难发现一滴墨水的影响范围是一个正方形
      在这里插入图片描述
    • 最中间的X是a,之后每往外一层就减b,知道a%b
    • 先将a%b的影响单独取出来。
    • 剩下若干层,从外到里分别是b,2b,3b,…,kb
    • 考虑每一层的矩形分别加b即可成为这个“回”字型的影响图。

    b b b b b
    b 2b 2b 2b b
    b 2b 3b 2b b
    b 2b 2b 2b b
    b b b b b

    • 将每一层分别加b,根据二维前缀和的方法即可快速加一个矩形
      (+b)-------- (-b)
      |***************|
      (-b)---------(+b)

    • 多层加在一起会变成
      b 0 0 0 0 0 0 -b
      0 b 0 0 0 0 -b 0
      0 0 b 0 0 -b 0 0
      0 0 0 b -b 0 0 0
      0 0 0 -b b 0 0 0
      0 0 -b 0 0 b 0 0
      0 -b 0 0 0 0 b 0
      -b 0 0 0 0 0 0 b

    • 将左上到右下和右上到左下的对角线分别计算。一段对角线的+b或-b依旧用差分区间修改。

    • 这样通过对角线的差分还原出上图,再通过二维前缀和即可还原出每一个位置。然后再用前缀和就可以实现O(1)查询。

    • 现在我们考虑一下出界的情况(即对角线有一部分在边界外时),这也是这题最为坑且难打的地方。
      -在这里插入图片描述

    • 例如红色的对角线上要全部+b

    • 但是出界的那一些显然不能找到地方填。

    • 所以我们考虑这些+b都是对右下的造成影响,所以出界的那一段就等价于橙色的那一段。

    • 所以将出界的部分影射到边界上后区间修改即可(又有一个差分)

    • 其它四个角以及出的不同的界要讨论一波,以此类推。

    • 最后复杂度O(w*h)

    • PS:注意一下精度(鬼知道为什么出题人还要求平均数,难道是专门卡精度的?

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #define maxm 2500005
    #define maxn 200005
    #define ll long long 
    using namespace std;
    
    int w,h,q,n,i,j,k,x,y,a,b,d,xx,yy,t;
    ll sum[maxm],level[maxm],pos[maxm],neg[maxm],row[maxm],col[maxm],cnt,ret;
    
    int I(int x,int y){
    	if (x<1||y<1||x>w||y>h) return 0; else 
    		return (x-1)*h+y;
    }
    
    void add(int x,int y,int d){
    	if (x<=w&&y<=h) 
    		level[I(max(x,1),max(y,1))]+=d;
    }
    
    int main(){
    	freopen("rezero07.in","r",stdin);
    	freopen("ceshi.out","w",stdout);
    //	freopen("ceshi.in","r",stdin);
    	scanf("%d%d",&w,&h);
    	scanf("%d",&n);
    	for(i=1;i<=n;i++) {
    		scanf("%d%d%d%d",&x,&y,&a,&b);
    		d=a/b-1;
    		add(x-d-1,y-d-1,a%b),add(x+d+2,y+d+2,a%b);
    		add(x-d-1,y+d+2,-a%b),add(x+d+2,y-d-1,-a%b);
    		//左上
    		xx=x-d,yy=y-d;
    		if (xx<1&&yy<1) {
    			t=min(1-xx,1-yy);
    			level[I(1,1)]+=t*b,xx+=t,yy+=t;
    		}
    		if (xx<1) {
    			t=1-xx;
    			row[I(1,yy)]+=b,row[I(1,yy+t)]-=b;
    			xx+=t,yy+=t;
    		}
    		if (yy<1) {
    			t=1-yy;
    			col[I(xx,1)]+=b,col[I(xx+t,1)]-=b;
    			xx+=t,yy+=t;
    		}
    		pos[I(xx,yy)]+=b;
    //		continue;
    		//右下
    		xx=x+d+2,yy=y+d+2;
    		if (xx<=w&&yy<=h) pos[I(xx,yy)]-=b;
    //		continue;
    		//左下
    		xx=x+d+1,yy=y-d;
    		if (xx>w&&y<1) {
    			t=min(xx-w,1-yy);
    			xx-=t,yy+=t;
    		}
    		if (xx>w) {
    			t=xx-w;
    			xx-=t,yy+=t;
    		}
    		if (yy<1) {
    			t=1-yy;
    			col[I(xx-t+1,1)]-=b;
    			if (xx+1<=w) col[I(xx+1,1)]+=b;
    			xx-=t,yy+=t;
    		}
    		neg[I(xx,yy)]-=b;
    		//右上
    		xx=x-d-1,yy=y+d+2;
    		if (xx>=1&&yy<=h) neg[I(xx,yy)]+=b;
    		else xx++,yy--;
    		if (xx<1&&yy>h) {
    			t=min(1-xx,yy-h);
    			xx+=t,yy-=t;
    		} 
    		if (xx<1) {
    			t=1-xx;
    			row[I(1,yy-t+1)]-=b;
    			if (yy+1<=h) row[I(1,yy+1)]+=b;
    			xx+=t,yy-=t;
    		}
    		if (yy>h) {
    			t=yy-h;
    			xx+=t,yy-=t;
    		}
    	}
    
    	for(i=1;i<=w;i++) for(cnt=0,j=1;j<=h;j++) 
    		cnt+=row[I(i,j)],level[I(i,j)]+=cnt;
    	for(j=1;j<=h;j++) for(cnt=0,i=1;i<=w;i++) 
    		cnt+=col[I(i,j)],level[I(i,j)]+=cnt;
    	for(x=1,y=1;y<=h;y++) for(cnt=0,i=x,j=y;i<=w&&j<=h;i++,j++)
    		cnt+=pos[I(i,j)],level[I(i,j)]+=cnt;
    	for(x=2,y=1;x<=w;x++) for(cnt=0,i=x,j=y;i<=w&&j<=h;i++,j++)
    		cnt+=pos[I(i,j)],level[I(i,j)]+=cnt;
    	for(x=1,y=1;x<=w;x++) for(cnt=0,i=x,j=y;i>=1&&j<=h;i--,j++) 
    		cnt+=neg[I(i,j)],level[I(i,j)]+=cnt;
    	for(x=w,y=2;y<=h;y++) for(cnt=0,i=x,j=y;i>=1&&j<=h;i--,j++)
    		cnt+=neg[I(i,j)],level[I(i,j)]+=cnt;
    	
    	for(i=1;i<=w;i++) for(j=1;j<=h;j++) 
    		level[I(i,j)]+=level[I(i-1,j)]+level[I(i,j-1)]-level[I(i-1,j-1)];
    	for(i=1;i<=w;i++) for(j=1;j<=h;j++) 
    		sum[I(i,j)]=level[I(i,j)]+sum[I(i-1,j)]+sum[I(i,j-1)]-sum[I(i-1,j-1)];
    	
    	
    	scanf("%d",&q);
    	while (q--) {
    		scanf("%d%d%d%d",&x,&y,&i,&j);
    		ll ans=sum[I(i,j)]-sum[I(x-1,j)]-sum[I(i,y-1)]+sum[I(x-1,y-1)];
    		ll s=(i-x+1)*(j-y+1);
    		ll ret=ans/s;
    		if ((ans%s)*2>=s) ret++;
    		printf("%lld
    ",ret);
    	}
    }
    
  • 相关阅读:
    angularjs+ionic的app端分页和条件
    js中对象的自定义排序
    angularJS入门笔记
    SpringBoot学习历程
    页面渲染流程
    跨域问题
    jquery知识点结合使用
    对bootstrap模态框的小尝试
    登录页面两端对齐的样式问题
    输入两个数字,将比较结果输出到页面
  • 原文地址:https://www.cnblogs.com/DeepThinking/p/11700940.html
Copyright © 2020-2023  润新知