CF Gym 101955G Best ACMer Solves the Hardest Problem

链接:https://codeforces.com/gym/101955/problem/G

题意:在二维平面上四种操作: 1,加一个带权的点; 2,删去一个点; 3,给一个点周围欧几里得距离为sqrt(k)的存在的点点权都加w; 4,查询一个到点欧几里得距离为sqrtk的点权和。

   x, y<6000, k<1e7, sigma(询问次数)<1e6,time:12s

题解:原本以为是数据结构,发现距离为k的x,y其实不多,直接存vector<pii>dis[maxk]暴力即可。

   注意:要判断nx,ny范围是否溢出,还有就是能不用memset尽量不要用,会超时。

#include <bits/stdc++.h>
using namespace std;

typedef pair<int, int> pii;

const int mod=6e3;
const int maxk=1e7+5;
const int maxn=6e3+5;

vector<pii> dis[maxk];
int vis[maxn][maxn], val[maxn][maxn];
int T, kase=0;

void pre_dis()
{
    for(int x=0; x<=3200; x++)
        for(int y=0; y<=3200; y++)
        {
            if(x*x+y*y>maxk) continue;
            dis[x*x+y*y].push_back(pii(x, y));
        }
}

void ins(int x, int y, int w)
{
    val[x][y]=w; vis[x][y]=kase;
}

void del(int x, int y)
{
    vis[x][y]=false;
}

bool check(int x, int y)
{
    if(x<0 || x>6000 || y<0 || y>6000) return false;
    if(vis[x][y]==kase) return true;
    return false;
}

void add(int x, int y, int k, int w)
{
    for(int i=0; i<dis[k].size(); i++)
    {
        int dx=dis[k][i].first, dy=dis[k][i].second;
        if(check(x+dx,y+dy)){
            val[x+dx][y+dy]+=w;
        }
        if(dx!=0 && check(x-dx,y+dy)){
            val[x-dx][y+dy]+=w;
        }
        if(dy!=0 && check(x+dx,y-dy)){
            val[x+dx][y-dy]+=w;
        }
        if(dx!=0&&dy!=0 && check(x-dx,y-dy)){
            val[x-dx][y-dy]+=w;
        }
    }
}

long long ask(int x, int y, int k)
{
    long long res=0;
    for(int i=0; i<dis[k].size(); i++)
    {
        int dx=dis[k][i].first, dy=dis[k][i].second;
        if(check(x+dx,y+dy)){
            res+=val[x+dx][y+dy];
        }
        if(dx!=0 && check(x-dx,y+dy)){
            res+=val[x-dx][y+dy];
        }
        if(dy!=0 && check(x+dx,y-dy)){
            res+=val[x+dx][y-dy];
        }
        if(dx!=0&&dy!=0 && check(x-dx,y-dy)){
            res+=val[x-dx][y-dy];
        }
    }
    return res;
}

int main()
{
    //freopen("in.txt", "r", stdin);
    pre_dis();
    for(scanf("%d", &T); T--; )
    {
        printf("Case #%d:\n", ++kase);
        //memset(vis, false, sizeof(vis)); 加上这句会超时
        int n, m;
        long long lastans=0;
        scanf("%d%d", &n, &m);
        for(int i=0; i<n; i++)
        {
            int x, y, w;
            scanf("%d%d%d", &x, &y, &w);
            ins(x, y, w);
        }
        for(int i=0; i<m; i++)
        {
            int cmd, x, y, w, k;
            scanf("%d%d%d", &cmd, &x, &y);
            x=(x+lastans)%mod+1;
            y=(y+lastans)%mod+1;
            if(cmd==1){
                scanf("%d", &w);
                ins(x, y, w);
            }
            else if(cmd==2){
                del(x, y);
            }
            else if(cmd==3){
                scanf("%d%d", &k, &w);
                add(x, y, k, w);
            }
            else if(cmd==4){
                scanf("%d", &k);
                printf("%I64d\n", lastans=ask(x, y, k));
            }
        }
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/Yokel062/p/11650122.html