来源
https://codeforces.com/group/TBxCTUW7hQ/contest/298611/problem/G
思路
对每个 k 预处理 x*x+y*y=k 的所有 (x,y) 。
那么每次修改和查询时可以暴力枚举所有符合条件的点,且在 sqrt(k)<=3200 的时间内完成 。
但这题比较坑的一点是维护每个点的数值,如果用6000*6000的数组维护,那对于每组数据都要一个3e7左右的memset来清零,会TLE。
这里有两种优化的方案:
- 用 map<pii,ll> 代替上述二维数组,clear的时间为 O(1),但询问会多一个log。
- 用一个 set
记录访问过的点,清零时遍历set将对应的点清零,缺点是内存使用较多。
方案一差点超时,方案二差点超内存,可以根据要求相应权衡。
代码
方案一
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<ll,ll> pii;
typedef vector<ll> vi;
#define dd(x) cout << #x << "=" << x << ","
#define de(x) cout << #x << "=" << x << endl
#define rep(i,a,b) for(ll i=(a);i<(b);++i)
#define per(i,a,b) for(ll i=(b-1);i>=a;--i)
#define all(x) (x).begin(),(x).end()
#define sz(x) (ll)(x).size()
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define endl "
"
#define lowbit(x) x&(-x)
const ll N = 20000;
const ll M = 1e9+7;
vector<pii> dxy[10000010];
map<pii,ll> g;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
for (ll i=0; i<=6000; i++)
for (ll j=0; j<=6000 && i*i+j*j<=10000000; j++){
dxy[i*i+j*j].pb(mp(i,j));
if (i!=0) dxy[i*i+j*j].pb(mp(-i,j));
if (j!=0) dxy[i*i+j*j].pb(mp(i,-j));
if (i!=0 && j!=0) dxy[i*i+j*j].pb(mp(-i,-j));
}
//***********************************
ll T;
cin>>T;
for (ll t=1; t<=T; t++){
cout<<"Case #"<<t<<":
";
g.clear();
ll n,m;
cin>>n>>m;
ll lastans=0;
for (ll i=1; i<=n; i++){
ll x,y,w;
cin>>x>>y>>w;
g[mp(x,y)]=w;
}
for (ll mm=1; mm<=m; mm++){
ll op,x,y,w,k;
cin>>op>>x>>y;
x=(x+lastans)%6000+1;
y=(y+lastans)%6000+1;
// cout<<op<<' '<<x<<' '<<y<<endl;
if (op==1){
cin>>w;
g[mp(x,y)]=w;
}
if (op==2){
g[mp(x,y)]=0;
}
if (op==3){
cin>>k>>w;
for (ll i=0; i<sz(dxy[k]); i++){
ll xx=x+dxy[k][i].fi;
ll yy=y+dxy[k][i].se;
if (xx<1 || xx>6000 || yy<1 || yy>6000) continue;
if (g[mp(xx,yy)]) g[mp(xx,yy)]+=w;
}
}
if (op==4){
cin>>k;
ll sum=0;
for (ll i=0; i<sz(dxy[k]); i++){
ll xx=x+dxy[k][i].fi;
ll yy=y+dxy[k][i].se;
if (xx<1 || xx>6000 || yy<1 || yy>6000) continue;
sum+=g[mp(xx,yy)];
// if (mm==2) cout<<dxy[k][i].fi<<','<<dxy[k][i].se<<endl;
}
cout<<sum<<endl;
lastans=sum;
}
}
}
return 0;
}
方案二
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<ll,ll> pii;
typedef vector<ll> vi;
#define dd(x) cout << #x << "=" << x << ","
#define de(x) cout << #x << "=" << x << endl
#define rep(i,a,b) for(ll i=(a);i<(b);++i)
#define per(i,a,b) for(ll i=(b-1);i>=a;--i)
#define all(x) (x).begin(),(x).end()
#define sz(x) (ll)(x).size()
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define endl "
"
#define lowbit(x) x&(-x)
vector<pii> dxy[10000010];
ll g[6010][6010];
set<pii> vis;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
for (ll i=0; i<=6000; i++)
for (ll j=0; j<=6000 && i*i+j*j<=10000000; j++){
dxy[i*i+j*j].pb(mp(i,j));
if (i!=0) dxy[i*i+j*j].pb(mp(-i,j));
if (j!=0) dxy[i*i+j*j].pb(mp(i,-j));
if (i!=0 && j!=0) dxy[i*i+j*j].pb(mp(-i,-j));
}
//***********************************
ll T;
cin>>T;
for (ll t=1; t<=T; t++){
cout<<"Case #"<<t<<":
";
ll n,m;
cin>>n>>m;
ll lastans=0;
for (ll i=1; i<=n; i++){
ll x,y,w;
cin>>x>>y>>w;
g[x][y]=w;
vis.insert(mp(x,y));
}
for (ll mm=1; mm<=m; mm++){
ll op,x,y,w,k;
cin>>op>>x>>y;
x=(x+lastans)%6000+1;
y=(y+lastans)%6000+1;
// cout<<op<<' '<<x<<' '<<y<<endl;
if (op==1){
cin>>w;
g[x][y]=w;
vis.insert(mp(x,y));
}
if (op==2){
g[x][y]=0;
}
if (op==3){
cin>>k>>w;
for (ll i=0; i<sz(dxy[k]); i++){
ll xx=x+dxy[k][i].fi;
ll yy=y+dxy[k][i].se;
if (xx<1 || xx>6000 || yy<1 || yy>6000) continue;
if (g[xx][yy]) g[xx][yy]+=w;
}
}
if (op==4){
cin>>k;
ll sum=0;
for (ll i=0; i<sz(dxy[k]); i++){
ll xx=x+dxy[k][i].fi;
ll yy=y+dxy[k][i].se;
if (xx<1 || xx>6000 || yy<1 || yy>6000) continue;
if (g[xx][yy]) sum+=g[xx][yy];
// if (mm==2) cout<<dxy[k][i].fi<<','<<dxy[k][i].se<<endl;
}
cout<<sum<<endl;
lastans=sum;
}
}
for (auto it:vis) g[it.fi][it.se]=0;
vis.clear();
}
return 0;
}
参考文献
[1] https://blog.csdn.net/jk_chen_acmer/article/details/98241012
[2] https://blog.csdn.net/qq_41925919/article/details/102018190