C. Celex Update(思维)

题目传送门

题意: 给你一个这样的图形,只能向右向左走,问你从(x1,y1)走到(x2,y2),对经过的数字进行求和,问你求得的和有多少种。

思路: 我们发现,同一种颜色的块,从右上到左下,大小一次增加1,比如我们要从(1,1)走到(3,3),最小的和是1-2-4-8-13,如果我们想在这个和的基础上+1,只要走4的左下那个格子,也就是5,其余的保持不变即可。那么我们很容易猜想到,所有总和就是最小到最大之间的所有数。最小的情况就是先一直向右,再一直向下;最大的情况就是先一直向下,再一直向右。

打个比方,我们要从点1走到图中标五角星的地方。

我们假设两种路径形成的矩形的较小边长是x,较大边长是y,我们就会发现,就是求0+1+2+…+x+x+x…+x+x-1+x-2+…+2+1+0,这就是最大值和最小值的差(对应路径中每一步,获得的差值。)然而中间的x有多少个呢?我们发现总共的步数有(y+x+1)步,前后两个(0+1+2+…+x-1),花费了2 * x步,所以有(y-x+1)个x,所以最后差值就是(y-x+1) * x+x * (x-1) ,也就是y * x 。所以最小值和最大值之间就有y *x+1个数,答案就是y * x+1。

代码:

#include<bits/stdc++.h>
#define endl '\n'
#define null NULL
#define ls p<<1
#define rs p<<1|1
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define pii pair<int,int>
#define ull unsigned long long
#define all(x) x.begin(),x.end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ct cerr<<"Time elapsed:"<<1.0*clock()/CLOCKS_PER_SEC<<"s.\n";
char *fs,*ft,buf[1<<20];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline int read(){int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
return x*f;}
using namespace std;
const int N=4e5+5;
const int inf=0x7fffffff;
const int mod=998244353;
const double eps=1e-6;
const double PI=acos(-1);
int a[N];
signed main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int x1,x2,y1,y2;
        cin>>x1>>y1>>x2>>y2;
        cout<<abs(x1-x2)*abs(y1-y2)+1<<endl;
    }
}

猜你喜欢

转载自blog.csdn.net/Joker_He/article/details/106378376