luo's oj P1733 三角形

题目链接
一个修改操作对一个查询操作的影响可以O(1)算。每次修改维护一个差分数
组,每一次复杂度 O(n)。
然后,每k次修改操作以后就重构整个三角形。
这样每次询问的话对于单个修改操作的查询用时就是 K。
然后每次重构时通过差分数组还原出原数组。再求出前缀和。用时是n^2=10^6。
每次查询扫一遍,复杂度q/k 。
重构次数不超过 。
复杂度O((q/k)n^2+qn+qk),当k=1000时可以通过该题。

#include<bits/stdc++.h>
#define N 1005
#define ll long long
using namespace std;
ll q[N][N],v[N][N],sum[N][N];
int n,Q,tot,a[N],b[N],c[N];
void add(int x,int y,int z){
    for(int t=0;t<z;t++){
        int i=x+t,j=y+t+1;
        q[i][y]+=1;
        q[i][j]-=1;
    }
}
void rebuild(){
    for(int i=1;i<=n;i++){
        int t=0;
        for(int j=1;j<=n;j++){
            t+=q[i][j];
            v[i][j]+=t;
            sum[i][j]=sum[i][j-1]+v[i][j];
            q[i][j]=0;
        }
    }
    tot=0;
}
int main(){
    scanf("%d%d",&n,&Q);
    while(Q--){
        int opt;
        scanf("%d",&opt);
        if(opt==1){
            tot++;
            scanf("%d%d%d",&a[tot],&b[tot],&c[tot]);
            add(a[tot],b[tot],c[tot]);
            if(tot==1000)rebuild();
        }else{
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            ll ans=0;
            for(int t=0;t<z;t++){
                int i=x+t,r=y+t;
                ans+=sum[i][r]-sum[i][y-1];
            }
            for(int i=1;i<=tot;i++){
                int aa=min(x+z-1,a[i]+c[i]-1);
                int bb=max(y,b[i]);
                int cc=max(x-y,a[i]-b[i]);
                int len=aa-bb-cc+1;
                if(x>aa||a[i]>aa)continue;//两个矩形上下无焦点 
                if(y+z-1<bb||b[i]+c[i]-1<bb)continue;//两个矩形左右无焦点 
                if(x+z-1-y<cc||a[i]+c[i]-1-b[i]<cc)continue;//斜率大于1则不可能 
                ans+=len<0 ? 0:len*(len+1)/2;
            }
            printf("%lld\n",ans);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36316033/article/details/80948301
今日推荐