考试的时候刚了T1两个小时线段树写了三个子任务结果发现看错了题目,于是接下来一个半小时我自闭了

result=历史新低

这告诉我们,打暴力要端正态度,尤其是在发现自己之前出锅的情况下要保持心态的平和,不能和今天的比赛一样后面差不多直接弃疗


T1:

题意就是我们要做多次倒三角的区间加,最后统计全部的异或和。不幸的是当我看到空间限制512MB的时候就直接暴力上线段树了,凉心出题人

正解是很巧妙的二维前缀和做法

考虑我们暴力怎么做--对倒三角的每一行差分,最后统计一次,这样的复杂度是$O(nq)$的

这个时候可以发现每一次倒三角我们改变的差分序列是可以二维差分优化的。其实就是对三角的竖着的直角边和那条斜边在维护差分数组,最后再统计答案就好了

其他的做法不会啊,果然还是太弱

#include<algorithm>
#include<cstdio>
#include<iostream>
#include<cstring>
#include<time.h>
using namespace std;
typedef long long ll;

const int N=3e3+15; 
ll n,q;
ll a[N][N],b[N][N],c[N][N],d[N][N],e[N][N];
inline ll read()
{
    char ch=getchar();
    ll s=0,f=1;
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9') {s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
    return s*f;
}
int main()
{
    freopen("u.in","r",stdin);
    freopen("u.out","w",stdout);
    //double st=clock();
    n=read();q=read();
    while (q--)
    {
        ll r=read(),c=read(),l=read(),s=read();
        a[r][c]+=s;a[r+l][c]-=s;
        b[r-c+n-1][r]-=s;b[r-c+n-1][r+l]+=s;
    }
    for (int i=1;i<=n;i++)    
        for (int j=1;j<=n;j++)
        {    
            c[i][j]=c[i-1][j]+a[i][j];
            d[i][j]=d[i-1][j-1]+b[i-j+n][i];
            e[i][j]=e[i][j-1]+c[i][j]+d[i][j]; 
        }
    /*for (int i=1;i<=n;i++)    
    {
        for (int j=1;j<=n;j++) 
            printf("%d ",c[i][j]+d[i][j]);
        printf("\n");
    }*/
    //printf("\n");
    ll ans=0;
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++) ans^=e[i][j];
    /*for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++) printf("%d ",e[i][j]);
        printf("\n");
    }*/
    printf("%lld\n",ans);
    //double ed=clock();
    //printf("%lf\n",ed-st); 
}
View Code

相关文章: