zoukankan      html  css  js  c++  java
  • URAL 1707 Hypnotoad's Secret

    URAL_1707

        这个题目一开始感觉好麻烦的,不过多读了几遍之后终于把模型抽象出来了,如果把(si,ti)看成一个点的话,那么后面就是不断地在查询某个矩形范围内是否至少存在一个点,如果该范围内至少存在一个点那么xj就是1,否则xj就是0。

        这让我联想到了POJ_2352数星星那个题,那个题是问一个点(x,y)的左边、下边以及左下方一共有多少个点(后面用sum(x,y)表示这个结果),而我们不难把Ural这个题目化归成那个题,如果矩形左下角是(x1,y1),右上角是(x2,y2)的话,那么最后结果就是sum(x2,y2)+sum(x1-1,y1-1)-sum(x1-1,y2)-sum(x2,y1-1)。

        也就是说我们只要把sum(x,y)都预处理出来就可以搞定这个题目了,而且预处理sum(x,y)的时间复杂度是O(N^2)的,是可以接受的。但是,看了题目中内存的限制心就凉了,如果开二维数组sum[x][y]表示这一结果的话64M是开不下的。

        不过,其实我们只要反问一句真的需要每个(x,y)的sum(x,y)都记录下来吗,问题也就迎刃而解了。因为显然需要保存下来的sum(x,y)个数是依赖于后续查询的次数的,通过计算后发现,后续需要查询的sum(x,y)其实并不多,于是我们就可以用哈希表把需要查询的sum(x,y)的(x,y)先保存下来,然后在预处理的时候遇到需要查询的sum(x,y)的(x,y)时,就将结果再写到哈希表中对应的位置即可。这样后面需要用到时,再直接从哈希中取就行了。

        求解sum(x,y)的过程应该也可以用线段树实现,但我暂时没有实际去敲,因为如果改用线段树去实现统计sum(x,y)这个模块的话,我的程序其他的部分就也要相应的改变不少地方,就等想敲的时候再敲一下吧,先睡觉去了……

        此外,对于q>20的情况需要计算那么一个诡异的表达式的值,由于模的那个数巨大,所以需要用高精度,这样为了节省时间我们可以先把高精度表示的(7^x)%200904040963的结果预处理出来,需要的时候再拿来做加法就可以了。

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #define MAXN 5010
    #define MAXP 570010
    #define MAXQ 500010
    #define HASH 1000003
    const long long int D = 200904040963ll, W = 15;
    int N, M, X, P, head[HASH], next[MAXQ], e, A[MAXN];
    struct Point
    {
        int x, y;
    }point[MAXP];
    struct Pointnum
    {
        int x, y, num;
    }pn[MAXQ];
    struct Exp
    {
        int a0, b0, c0, d0, da, db, dc, dd, q;
    }exp[360];
    struct BigInteger
    {
        int a[W];
        void init(long long int x)
        {
            int i;
            for(i = 0; i < W; i ++)
            {
                a[i] = x % 10;
                x /= 10;
            }
        }
        BigInteger add(BigInteger &b)
        {
            int i;
            long long int s, c;
            BigInteger res;
            c = 0;
            for(i = 0; i < W; i ++)
            {
                s = a[i] + b.a[i] + c;
                res.a[i] = s % 10;
                c = s / 10;
            }
            c = 0;
            for(i = W - 1; i >= 0; i --)
            {
                s = c * 10 + res.a[i];
                c = s % D;
            }
            res.init(c);
            return res;
        }
        BigInteger multiply(int k)
        {
            int i, j;
            long long int s, c;
            BigInteger res;
            c = 0;
            for(i = 0; i < W; i ++)
            {
                s = a[i] * k + c;
                res.a[i] = s % 10;
                c = s / 10;
            }
            c = 0;
            for(i = W - 1; i >= 0; i --)
            {
                s = c * 10 + res.a[i];
                c = s % D;
            }
            res.init(c);
            return res;
        }
        void print()
        {
            int i;
            for(i = W - 1; i > 0; i --)
                if(a[i])
                    break;
            for(; i >= 0; i --)
                printf("%d", a[i]);
        }
    }seven[360];
    int cmpp(const void *_p, const void *_q)
    {
        Point *p = (Point *)_p, *q = (Point *)_q;
        if(p->x == q->x)
            return p->y < q->y ? -1 : 1;
        return p->x < q->x ? -1 : 1;
    }
    void prepare()
    {
        int i;
        BigInteger t;
        seven[0].init(1);
        for(i = 1; i < 345; i ++)
            seven[i] = seven[i - 1].multiply(7);
    }
    void doswap(int &x, int &y)
    {
        if(x > y)
        {
            int t;
            t = x, x = y, y = t;
        }
    }
    void getabcd(int i, int j, int &aj, int &bj, int &cj, int &dj)
    {
        aj = ((exp[i].a0 + j * exp[i].da) % N + N) % N;
        bj = ((exp[i].b0 + j * exp[i].db) % N + N) % N;
        cj = ((exp[i].c0 + j * exp[i].dc) % N + N) % N;
        dj = ((exp[i].d0 + j * exp[i].dd) % N + N) % N;
    }
    int hash(int x, int y)
    {
        return (x * N + y) % HASH;
    }
    void Insert(int x, int y)
    {
        if(x < 0 || y < 0)
            return ;
        int i, h = hash(x, y);
        for(i = head[h]; i != -1; i = next[i])
            if(pn[i].x == x && pn[i].y == y)
                break;
        if(i == -1)
        {
            pn[e].x = x, pn[e].y = y;
            next[e] = head[h], head[h] = e;
            ++ e;
        }
    }
    void init()
    {
        int i, j, k, s0, t0, ds, dt, aj, bj, cj, dj;
        X = 0;
        for(i = 0; i < M; i ++)
        {
            scanf("%d%d%d%d%d", &s0, &t0, &ds, &dt, &k);
            for(j = 0; j < k; j ++)
            {
                point[X].x = ((s0 + j * ds) % N + N) % N;
                point[X].y = ((t0 + j * dt) % N + N) % N;
                ++ X;
            }
        }
        qsort(point, X, sizeof(point[0]), cmpp);
        scanf("%d", &P);
        e = 0;
        memset(head, -1, sizeof(head));
        for(i = 0; i < P; i ++)
        {
            scanf("%d%d%d%d%d%d%d%d%d", &exp[i].a0, &exp[i].b0, &exp[i].c0, &exp[i].d0, &exp[i].da, &exp[i].db, &exp[i].dc, &exp[i].dd, &exp[i].q);
            for(j = 0; j < exp[i].q; j ++)
            {
                getabcd(i, j, aj, bj, cj, dj);
                doswap(aj, bj), doswap(cj, dj);
                Insert(bj, dj), Insert(aj - 1, dj), Insert(aj - 1, cj - 1), Insert(bj, cj - 1);
            }
        }
    }
    void refresh(int x, int y, int num)
    {
        int i, h = hash(x, y);
        for(i = head[h]; i != -1; i = next[i])
            if(pn[i].x == x && pn[i].y == y)
                break;
        if(i != -1)
            pn[i].num = num;
    }
    int getnum(int x, int y)
    {
        if(x < 0 || y < 0)
            return 0;
        int i, h = hash(x, y);
        for(i = head[h]; i != -1; i = next[i])
            if(pn[i].x == x && pn[i].y == y)
                break;
        return pn[i].num;
    }
    void normalquery(int i)
    {
        int j, aj, bj, cj, dj;
        for(j = 0; j < exp[i].q; j ++)
        {
            getabcd(i, j, aj, bj, cj, dj);
            doswap(aj, bj), doswap(cj, dj);
            if(getnum(bj, dj) + getnum(aj - 1, cj - 1) - getnum(aj - 1, dj) - getnum(bj, cj - 1) > 0)
                printf("1");
            else
                printf("0");
        }
        printf("\n");
    }
    void specialquery(int i)
    {
        int j, aj, bj, cj, dj;
        BigInteger ans;
        ans.init(0);
        for(j = 0; j < exp[i].q; j ++)
        {
            getabcd(i, j, aj, bj, cj, dj);
            doswap(aj, bj), doswap(cj, dj);
            if(getnum(bj, dj) + getnum(aj - 1, cj - 1) - getnum(aj - 1, dj) - getnum(bj, cj - 1) > 0)
                ans = ans.add(seven[j]);
        }
        ans.print();
        printf("\n");
    }
    void solve()
    {
        int i, j, k, p, cnt, ans;
        memset(A, 0, sizeof(A));
        p = 0;
        for(i = 0; i < N; i ++)
        {
            ans = 0;
            for(j = 0; j < N; j ++)
            {
                cnt = 0;
                while(p < X && point[p].x == i && point[p].y == j)
                    ++ p, ++ cnt;
                A[j] += cnt;
                ans += A[j];
                refresh(i, j, ans);
            }
        }
        for(i = 0; i < P; i ++)
        {
            if(exp[i].q <= 20)
                normalquery(i);
            else
                specialquery(i);
        }
    }
    int main()
    {
        prepare();
        while(scanf("%d%d", &N, &M) == 2)
        {
            init();
            solve();
        }
        return 0;
    }
  • 相关阅读:
    Codeforces_739_B
    Codeforces_732_D
    D
    C
    E
    商汤AI园区的n个路口(中等)
    D. The Fair Nut and the Best Path
    HDU6446
    分解质因数(线性筛)
    D. Extra Element
  • 原文地址:https://www.cnblogs.com/staginner/p/2443274.html
Copyright © 2011-2022 走看看