Best ACMer Solves the Hardest Problem【数据预处理】

来源

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 "\n"
#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<<":\n";
		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 "\n"
#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<<":\n";
		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

posted @ 2020-10-21 16:31  Synnn  阅读(280)  评论(0编辑  收藏  举报