ACM学习历程—SNNUOJ 1239 Counting Star Time(树状数组 && 动态规划 && 数论)

http://219.244.176.199/JudgeOnline/problem.php?id=1239

这是这次陕西省赛的G题,题目大意是一个n*n的点阵,点坐标从(1, 1)到(n, n),每个点都有权值,然后从(x, y)引x轴的垂线,然后构成一个三角形,三个顶点分别是(0, 0),(x, 0)和(x, y)。求三角形内点的权值和,包括边界,n的范围是1000,m的范围是100000,说起来也比较坑。。学弟n*m的复杂度竟然水过去了,目测比赛数据比较水。。不过我挂到我们OJ上给了一组随机数据,一组极限数据,然后学弟就T掉了。。(坑学弟系列。。)

不水了,这个题目感觉本身是个很好的题。

刚拿到题,我的第一反应肯定是求出所有的p(x, y),然后往dp的转移方程去考虑。但是发现单纯的递推感觉问题更复杂了。。

但是发现一个重要点就是,斜率小的点,必定被它后面斜率大的点包括。然后,我就想到按x轴枚举每一列,维护每个斜率出现的权值和。那么每一个大的斜率必然是前面枚举过的小的斜率的和,于是便可以树状数组维护了。关键是解决斜率的离散化,我的第一想法是map来进行Hash。当时有了这个思路,本来想着应该可以抢个一血什么的。。结果打到一个小时左右的时候,发现这题已经被好几个人A掉了。。。(什么鬼。。)。我的第一发T了。。通过本地测试,map那个Hash实在太慢了。。于是我开始考虑怎么优化这个Hash,想了好几个办法,要满足y1/x1 < y2/x2,并且Hash(x1, y1) < Hash(x2, y2)的函数实在是没办法。。中间还交了两次错误的Hash方法。。最后队友提醒下,发现那个离散化的过程完全可以一开始预处理,不需要每组数据在线完成,因为数据只有1000*1000,那么所有斜率必然在这个范围内。然后终于A掉了。。

预处理复杂度:O(n*n*log(n*n))

打表:O(n*n*log(n*n))

在线查询:O(m)

最后总的复杂度是O(n*n*log(n*n)+T*(m+n*n*log(n*n)))

如果m大一点的话,这个复杂度还是比较优秀的。。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <string>
#define LL long long

using namespace std;

const int maxM = 1005;
const int maxN = 1000005;
LL d[maxN];

int lowbit(int x)
{
    return x&(-x);
}

void add(int id, int pls)
{
    while(id <= maxN)//id最大是maxN
    {
        d[id] += pls;
        id += lowbit(id);
    }
}

LL sum(int to)
{
    LL s = 0;
    while(to > 0)
    {
        s = s + d[to];
        to -= lowbit(to);
    }
    return s;
}

int gcd(int a, int b)
{
    int r;
    while (b != 0)
    {
        r = b;
        b = a%b;
        a = r;
    }
    return a;
}

struct node
{
    int x, y;

    void create(int xx, int yy)
    {
        int t = gcd(xx, yy);
        x = xx/t;
        y = yy/t;
    }

    bool operator<(node k) const
    {
        return k.x*y < k.y*x;
    }
};

int n, a[maxM][maxM];
LL p[maxM][maxM];
map<node, int> Hash;

void init()
{
    node t;
    for (int i = 1; i < maxM; ++i)
        for (int j = 1; j < maxM; ++j)
        {
            t.create(i, j);
            Hash[t] = 233;
        }
    map<node, int>::iterator it;
    int cnt = 1;
    for (it = Hash.begin(); it != Hash.end(); ++it)
        it->second = cnt++;
}

void input()
{
    memset(d, 0, sizeof(d));
    node t;
    int to;
    scanf("%d", &n);
    for (int i = n; i >= 1; --i)
        for (int j = 1; j <= n; ++j)
            scanf("%d", &a[i][j]);
    for (int j = 1; j <= n; ++j)
    {
        for (int i = 1; i <= n; ++i)
        {
            t.create(j, i);
            to = Hash[t];
            add(to, a[i][j]);
            p[j][i] = sum(to);
        }
    }
}

void work()
{
    int m, u, v;
    scanf("%d", &m);
    for (int i = 1; i <= m; ++i)
    {
        scanf("%d%d", &u, &v);
        printf("%lld\n", p[u][v]);
    }
}

int main()
{
    //freopen("test.in", "r", stdin);
    //freopen("test.out", "w", stdout);
    init();
    int T;
    scanf("%d", &T);
    for (int times = 1; times <= T; ++times)
    {
        printf("Case #%d:\n", times);
        input();
        work();
    }
    return 0;
}

时间: 2024-08-02 08:07:33

ACM学习历程—SNNUOJ 1239 Counting Star Time(树状数组 && 动态规划 && 数论)的相关文章

13年山东省赛 Boring Counting(离线树状数组or主席树+二分or划分树+二分)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud 2224: Boring Counting Time Limit: 3 Sec  Memory Limit: 128 MB Description In this problem you are given a number sequence P consisting of N integer and Pi is the ith element in the sequence.

TOJ 4105 Lines Counting(离线树状数组)

4105.   Lines Counting Time Limit: 2.0 Seconds   Memory Limit: 150000K Total Runs: 152   Accepted Runs: 47 On the number axis, there are N lines. The two endpoints L and R of each line are integer. Give you M queries, each query contains two interval

ACM学习历程—SNNUOJ 1110 A Simple Problem(递推 &amp;&amp; 逆元 &amp;&amp; 组合数学 &amp;&amp; 快速幂)(2015陕西省大学生程序设计竞赛K题)

Description Assuming a finite – radius “ball” which is on an N dimension is cut with a “knife” of N-1 dimension. How many pieces will the “ball” be cut into most?However, it’s impossible to understand the following statement without any explanation.L

ACM学习历程—SNNUOJ 1110 传输网络((并查集 &amp;&amp; 离线) || (线段树 &amp;&amp; 时间戳))(2015陕西省大学生程序设计竞赛D题)

Description Byteland国家的网络单向传输系统可以被看成是以首都 Bytetown为中心的有向树,一开始只有Bytetown建有基站,所有其他城市的信号都是从Bytetown传输过来的.现在他们开始在其他城市陆 续建立了新的基站,命令“C x“代表在城市x建立了一个新的基站,不会在同一个城市建立多个基站:城市编号为1到n,其中城市1就是首都Bytetown.在建立基站的过程中他们还 会询问某个城市的网络信号是从哪个城市传输过来的,命令”Q x“代表查询城市x的来源城市. Inpu

ACM学习历程—HDU 4287 Intelligent IME(字典树 || map)

Description We all use cell phone today. And we must be familiar with the intelligent English input method on the cell phone. To be specific, the number buttons may correspond to some English letters respectively, as shown below: 2 : a, b, c    3 : d

ACM学习历程—HDU2222 Keywords Search(字典树)

Keywords Search Description In the modern time, Search engine came into the life of everybody like Google, Baidu, etc.       Wiskey also wants to bring this feature to his image retrieval system.       Every image have a long description, when users

ACM学习历程——HDU3333 Turing Tree(线段树 &amp;&amp; 离线操作)

Problem Description After inventing Turing Tree, 3xian always felt boring when solving problems about intervals, because Turing Tree could easily have the solution. As well, wily 3xian made lots of new problems about intervals. So, today, this sick t

ACM学习历程—POJ1151 Atlantis(扫描线 &amp;&amp; 线段树)

Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of the island. But unfortunately, these maps describe different regions of Atlantis. Your friend

POJ 2352 star (树状数组)

Language: Default Stars Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 35318   Accepted: 15326 Description Astronomers often examine star maps where stars are represented by points on a plane and each star has Cartesian coordinates. Let