2012icpc杭州模拟

I 签到c语言题

K 裸最小生成树 不小心wa了一发

H 任意两点最短路的最长路 map+spfa水过...讲道理算复杂度是常数很大的O(ne) 加上map 还以为会tle

J 看好题意 暴力状态压缩枚举就好

B 计算几何 枚举角度计算点到矩形距离

 

C看了半天觉得不可做..没怎么往dp想... 正解是动态规划(或者说递推)...有点难

D 二维树状数组+坐标旋转+离散化(或者线段树套树 不用坐标旋转) ..(现场赛时不卡内存 不用离散化)线下比线上难得多系列

 

F 计算几何 相当于判断点是否在多边形内 不是太难 现场可能是精度要求太高导致个位数ac率..(完全精度?)

A 复杂数据结构之伸展树..据说略模板

 

E G 2个防ak题...

 

 

 

简单题还比较顺利..还可以再快点...

中等题bcdf可做 计算几何比较占电脑 需要良好的模板和熟练度... dp看智力 几乎不占键盘时间 感觉不可做的中等题往dp想好了..

中期有不太难的计算几何可以上机搞

现场赛不限内存 据说d题半G的数组ac了 只优化内存的离散化几乎不用写...

树状数组有必要学习一个..

应该备良好的图论及计算几何模板..

 

C动态规划代码:

#include<cstdio>

#include<cstring>

int c[1000005], sum[1000005], num[1000005], pre[1000005], a[1000005];

long long dp[1000005];//dp值是O(n^2)级 会超int

int main()

{

    int i, x, n, m;

    while (scanf("%d", &n) && n)

    {

        for (i = 1; i <= n; i++) scanf("%d", &a[i]);

        memset(pre, 0, sizeof(pre)), memset(c, 0, sizeof(c));

        for (i = 1; i <= n; i++)//c[i] 间距为i的相同数的对数 第一次出现则记录数组下标

            c[i - pre[a[i]]]++, pre[a[i]] = i;

        sum[n] = c[n];

        for (i = n - 1; i>0; i--)//sum[i] 间距大于等于i的相同数的对数

            sum[i] = sum[i + 1] + c[i];

        memset(c, 0, sizeof(c));

        c[a[n]] = 1, num[1] = 1;

        for (i = 2; i <= n; i++)//num[i] 后i个数中不同数的个数

            if (!c[a[n - i + 1]])//c[i] 数i是否出现过 相当于vis

                num[i] = num[i - 1] + 1, c[a[n - i + 1]] = 1;

            else

                num[i] = num[i - 1];

        dp[1] = n;

        for (i = 2; i <= n; i++)//dp[i]相当于dp[i-1]去掉最后1组 再在之前每组后面加1个元素

            //所以 减去后i-1个不同数次数 后面加的数里 只要前一次出现相同元素不小于i 就+1

            dp[i] = dp[i - 1] - num[i - 1] + sum[i];//总复杂度是常数很大的O(N)

        scanf("%d", &m);

        while (m--&&scanf("%d", &x))

            printf("%lld\n", dp[x]);

    }

}

 

D 二维树状数组(模板)+坐标旋转+离散化:

#include <cstdio>

#include <cstring>

#include <algorithm>

using namespace std;

#define mm 80005

int n, m, w, e, h[mm << 5], ss[mm << 5], pp[mm], xx[mm], yy[mm], zz[mm];

void ha(int x, int y)//离散化

{//对与每个位运算涉及的点都要离散化

    for (int i = x; i <= w; i += i&-i)

        for (int j = y; j <= w; j += j&-j)

            h[e++] = i * w + j;//转化至一维

}

void add(int x, int y, int d)

{

    for (int i = x; i <= w; i += i&-i)

        for (int j = y; j <= w; j += j&-j)

            ss[lower_bound(h + 1, h + e, i*w + j) - h] += d;

}

int sum(int x, int y)

{

    int s = 0;

    for (int i = x; i; i -= i&-i)

        for (int j = y; j; j -= j&-j)

        {

            int pos = lower_bound(h + 1, h + e, i*w + j) - h;

            if (h[pos] == i * w + j)

                s += ss[pos];

        }

    return s;

}

int main()

{

    int a, b, c, d, x, y;

    while (scanf("%d", &n)  && n)

    {

        e = 1, w = n << 1;

        scanf("%d", &m);

        memset(ss, 0, sizeof(ss));

        for (int i = 1; i <= m; i++)

        {

            scanf("%d%d%d%d", pp + i, xx + i, yy + i, zz + i);

            x = xx[i] - yy[i] + n, y = xx[i] + yy[i];

            if (pp[i] == 1) ha(x, y);

        }

        sort(h + 1, h + e), e = unique(h + 1, h + e) - h;

        for (int i = 1; i <= m; i++)

        {

            x = xx[i] - yy[i] + n, y = xx[i] + yy[i];

            if (pp[i] == 1) add(x, y, zz[i]);

            else {

                a = max(1, x - zz[i]), b = max(1, y - zz[i]);

                c = min(w, x + zz[i]), d = min(w, y + zz[i]);

                printf("%d\n", sum(c, d) - sum(c, b - 1) - sum(a - 1, d) + sum(a - 1, b - 1));

            }

        }

    }

}

离散化的地方很妙..

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值