2019ICPC南京网络赛A题 The beautiful values of the palace(三维偏序)

2019ICPC南京网络赛A题

The beautiful values of the palace

https://nanti.jisuanke.com/t/41298

Here is a square matrix of n * nnn, each lattice has its value (nn must be odd), and the center value is n * nnn. Its spiral decline along the center of the square matrix (the way of spiral decline is shown in the following figure:)

The grid in the lower left corner is (1,1) and the grid in the upper right corner is (n , n)

Now I can choose mm squares to build palaces, The beauty of each palace is equal to the digital sum of the value of the land which it is located. Such as (the land value is 123213123213,the beautiful values of the palace located on it is 1+2+3+2+1+3=121+2+3+2+1+3=12) (666666 -> 1818) (456456 ->1515)

Next, we ask pp times to the sum of the beautiful values of the palace in the matrix where the lower left grid(x_1,y_1x1,y1), the upper right square (x_2,y_2x2,y2).

Input

The first line has only one number TT.Representing TT-group of test data (T\le 5)(T≤5)

The next line is three number: n  m  pn m p

The mm lines follow, each line contains two integers the square of the palace (x, y )(x,y)

The pp lines follow, each line contains four integers : the lower left grid (x_1,y_1)(x1,y1) the upper right square (x_2,y_2)(x2,y2)

Output

Next, p_1+p_2...+p_Tp1+p2...+*p**T* lines: Represent the answer in turn(n \le 10^6)(m , p \le 10^5)(n≤106)(m,p≤105)

样例输入复制

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

样例输出复制

5
18
23
17

思路:

三维偏序的题目

首先根据推公式可以把每一个点在螺旋矩阵中对应的数值求出。

然后我们把m个点当做成m个加点操作,

p个询问,每一个询问分解为4个子询问,对同一个答案计算贡献。

因为根据容斥原理,我们可以把求二维前缀和分解为4个以左下角点为(0,0)的4个前缀和来处理。,

然后对x,y进行排序,

坐标相同时,一定要加点的操作排在询问前面。

然后用树桩数组来维护偏序问题即可。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
#define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
#define du2(a,b) scanf("%d %d",&(a),&(b))
#define du1(a) scanf("%d",&(a));
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {a %= MOD; if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}

inline void getInt(int *p);
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/


ll tree[maxn];
int lowbit(int x)
{
    return -x & x;
}
ll ask(int x)
{
    ll res = 0ll;
    while (x) {
        res += tree[x];
        x -= lowbit(x);
    }
    return res;
}
void add(int x, ll val)
{
    while (x < maxn) {
        tree[x] += val;
        x += lowbit(x);
    }
}
ll re_val(ll x)
{
    ll sum = 0;
    while (x > 0) {
        sum += x % 10;
        x /= 10;
    }
    return sum;
}
long long index(long long y, long long x, long long n)
{
    long long mid = (n + 1) / 2;
    long long p = max(abs(x - mid), abs(y - mid));
    long long ans = n * n - (1 + p) * p * 4;
    long long sx = mid + p, sy = mid + p;
    if (x == sx && y == sy) {
        return ans;
    } else {
        if (y == sy || x == sx - 2 * p) {
            return ans + abs(x - sx) + abs(y - sy);
        } else {
            return ans + 8 * p - abs(x - sx) - abs(y - sy);
        }
    }
}
int tot;
struct node {
    int type;
    int id;
    ll k;
    ll x, y;
    ll val;
    node() {}
    node(int tt, int idd, ll kk, ll xx, ll yy, ll vv)
    {
        id = idd;
        type = tt;
        k = kk;
        x = xx;
        y = yy;
        val = vv;
    }
} a[maxn];
bool cmp(node aa, node bb)
{
    if (aa.y != bb.y) {
        return aa.y < bb.y;
    } else if (aa.x != bb.x) {
        return aa.x < bb.x;
    } else {
        return aa.type < bb.type;
    }
}
ll ans[maxn];
void solve()
{
    repd(i, 1, tot) {
        if (a[i].type) {
            ans[a[i].id] += a[i].k * ask(a[i].x);
        } else {
            add(a[i].x, a[i].val);
        }
    }
}
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    int t;
    du1(t);
    while (t--) {
        int n, m, p;
        du3(n, m, p);
        MS0(tree);
        tot = 0;
        repd(i, 1, m) {
            int x, y;
            du2(x, y);
            ll val = re_val(index(x, y, n));
            a[++tot] = node(0, 0, 1ll, x, y , val);
        }
        repd(i, 1, p) {
            ans[i] = 0ll;
            int lx, ly, rx, ry;
            du3(lx, ly, rx); du1(ry);
            a[++tot] = node(1, i, 1ll, rx, ry , 0);
            a[++tot] = node(1, i, 1ll, lx - 1, ly - 1 , 0);
            a[++tot] = node(1, i, -1ll, rx, ly - 1 , 0);
            a[++tot] = node(1, i, -1ll, lx - 1, ry , 0);
        }
        sort(a + 1, a + 1 + tot, cmp);
        solve();
        repd(i, 1, p) {
            printf("%lld\n", ans[i] );
        }
    }
    return 0;
}

inline void getInt(int *p)
{
    char ch;
    do {
        ch = getchar();
    } while (ch == ' ' || ch == '\n');
    if (ch == '-') {
        *p = -(getchar() - '0');
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 - ch + '0';
        }
    } else {
        *p = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 + ch - '0';
        }
    }
}



全部评论

相关推荐

自从我室友在计算机导论课上听说了“刷&nbsp;LeetCode&nbsp;是进入大厂的敲门砖”,整个人就跟走火入魔了一样。他在宿舍门口贴了一张A4纸,上面写着:“正在&nbsp;DP,请勿打扰,否则&nbsp;Time&nbsp;Limit&nbsp;Exceeded。”日记本的扉页被他用黑色水笔加粗描了三遍:“Talk&nbsp;is&nbsp;cheap.&nbsp;Show&nbsp;me&nbsp;the&nbsp;code。”连宿舍聚餐,他都要给我们讲解:“今天的座位安排可以用回溯算法解决,但为了避免栈溢出,我建议用动态规划。来,这是状态转移方程:dp[i][j]&nbsp;代表第&nbsp;i&nbsp;个人坐在第&nbsp;j&nbsp;个位置的最优解。”我让他去楼下取个快递,他不直接去,非要在门口踱步,嘴里念念有词:“这是一个图的遍历问题。从宿舍楼(root)到驿站(target&nbsp;node),我应该用&nbsp;BFS&nbsp;还是&nbsp;DFS?嗯,求最短路径,还是广度优先好。”和同学约好出去开黑,他会提前发消息:“集合点&nbsp;(x,&nbsp;y),我们俩的路径有&nbsp;k&nbsp;个交点,为了最小化时间复杂度,应该在&nbsp;(x/2,&nbsp;y/2)&nbsp;处汇合。”有一次另一个室友低血糖犯了,让他帮忙找颗糖,他居然冷静地分析道:“别急,这是一个查找问题。零食箱是无序数组,暴力查找是&nbsp;O(n)。如果按甜度排序,我就可以用二分查找,时间复杂度降到&nbsp;O(log&nbsp;n)。”他做卫生也要讲究算法效率:“拖地是典型的岛屿问题,要先把连通的污渍区块都清理掉。倒垃圾可以用双指针法,一个指针从左往右,一个从右往左,能最快匹配垃圾分类。”现在我们宿舍的画风已经完全变了,大家不聊游戏和妹子,对话都是这样的:“你&nbsp;Two&nbsp;Sum&nbsp;刷了几遍了?”“别提了,昨天遇到一道&nbsp;Hard&nbsp;题,我连暴力解都想不出来,最后只能看题解。你呢?”“我动态规划还不行,总是找不到最优子结构。今天那道接雨水给我整麻了。”……LeetCode&nbsp;真的害了我室友!!!
老六f:编程嘉豪来了
AI时代还有必要刷lee...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务