• 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

  • 相关阅读:
    AR_销售订单收款基本操作(流程)
    AR_标准应收过账至总账基本操作(流程)
    AP_建立银行信息总行、分行、账户(设定)
    AP_费用报表报销基本操作(流程)
    AP_付款方式汇总:标准付款、退款退货付款、撤销付款(概念)
    AP_标准预付款核销基本操作(流程)
    AP_标准采购单付基本操作(流程)
    AP_创建标准发票后会计科目的变化(概念)
    Workflow_标准控件Wait_For_Flow和Contiune_Flow的用法(案例)
    Workflow_将一个消息同时发给通过用户(案例)
  • 原文地址:https://www.cnblogs.com/fdulinxin/p/13853125.html
Copyright © 2020-2023  润新知