icpc2019 南京网络赛选拔赛 A 二维数点+蛇形填数
做法:
把每次询问按容斥定理分成四个二维前缀和查询,然后对x排序,扫描线即可
#pragma GCC optimize("Ofast") #include<bits/stdc++.h> #define ll long long #define ull unsigned long long #define fi first #define se second #define mp make_pair #define pii pair<ll,ll> #define all(x) x.begin(),x.end() #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) #define per(ii,a,b) for(int ii=b;ii>=a;--ii) #define forn(i,x,g,e) for(int i=g[x];i;i=e[i].next) #define show(x) cout<<#x<<"="<<x<<endl #define showa(a,b) cout<<#a<<'['<<b<<"]="<<a[b]<<endl #define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl #define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define show4(w,x,y,z) cout<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define show5(v,w,x,y,z) cout<<#v<<"="<<v<<" "<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define showmm(x,a,b) rep(i,0,a) rep(j,0,b) cout<<#x<<'['<<i<<']'<<'['<<j<<"]="<<x[i][j]<<(" \n"[j==b]) #define showm(x,a,b) rep(i,0,a) rep(j,0,b) cout<<x[i][j]<<(" \n"[j==b]) #define showa1(x,a,b) cout<<#x<<":\n";rep(i,a,b) showa(x,i);cout<<endl #define showa2(x,a,b) cout<<#x<<": ";rep(i,a,b) cout<<x[i]<<' ';cout<<endl using namespace std;//head const int maxn=1e6+10,maxm=2e6+10; const ll INF=0x3f3f3f3f,mod=1e9+7; int casn,n,m,k,num[maxn]; namespace fastio{//@支持读取整数,字符串,输出整数@ bool isdigit(char c){return c >= 48 && c <= 57;} const int maxsz=1e7; class fast_iostream{public: char ch=get_char(); bool endf=1,flag; char get_char(){ static char buffer[maxsz],*a=buffer,*b=buffer; return b==a&&(b=(a=buffer)+fread(buffer,1,maxsz, stdin),b==a)?EOF:*a++; } template<typename type>bool get_int(type& tmp){ flag=tmp=0; while(!isdigit(ch)&&ch!=EOF){flag=ch=='-';ch=get_char();}; if(ch==EOF)return endf=0; do{tmp=ch-48+tmp*10;}while(isdigit(ch=get_char())); if(flag)tmp=-tmp; return 1; } int get_str(char* str){ char* tmp=str; while(ch=='\r'||ch=='\n'||ch==' ')ch=get_char(); if(ch==EOF)return(endf=0),*tmp=0; do{*(tmp++)=ch;ch=get_char();}while(ch!='\r'&&ch!='\n'&&ch!=' '&&ch!=EOF); *(tmp++)=0; return(int)(tmp-str-1); } fast_iostream& operator>>(char* tmp){get_str(tmp);return *this;} template<typename type>fast_iostream& operator>>(type& tmp){get_int(tmp);return *this;} operator bool() const {return endf;} }; } fastio::fast_iostream io; int a[maxn]; struct bit{ ll node[maxn],n; inline int lb(int x) {return x&(-x);} void init(int _n){n=_n;fill_n(node,n+2,0);} inline void update(int pos,ll val){ if(pos>0)for(int i=pos;i<=n;i+=lb(i)) node[i]+=val; } inline ll ask(int pos){ ll sum=0; if(pos>0)for(int i=pos;i;i-=lb(i)) sum+=node[i]; return sum; } inline ll query(int l,int r){ return ask(r)-ask(l-1); } }tree; struct node{int x,y,id;ll val;}point[maxn],ask[maxn]; int cmp(node a,node b){ if(a.x==b.x) return a.y<b.y; return a.x<b.x; } ll ans[maxn]; ll getv(int x,int y){ x-=n/2+1;y-=n/2+1; ll tmp=max(abs(x),abs(y)); if(x>=y) return 1ll*n*n-4*tmp*tmp-2*tmp-x-y; else return 1ll*n*n-4*tmp*tmp+2*tmp+x+y; } int cal(ll v){ ll ans=0; while(v){ans+=v%10;v/=10;} return ans; } int main() { io>>casn; while(casn--){ io>>n>>k>>m; int cnt=0; rep(i,1,k){ io>>point[i].x>>point[i].y; point[i].id=i; point[i].val=cal(getv(point[i].x,point[i].y)); } sort(point+1,point+1+k,cmp); rep(i,1,m){ ans[i]=0; int a,b,c,d; io>>a>>b>>c>>d; ask[++cnt]={c,d,i,1}; ask[++cnt]={a-1,d,i,-1}; ask[++cnt]={c,b-1,i,-1}; ask[++cnt]={a-1,b-1,i,1}; } sort(ask+1,ask+1+cnt,cmp); int l=1; tree.init(n+1); rep(i,1,cnt){ while(l<=k&&point[l].x<=ask[i].x){ tree.update(point[l].y,point[l].val); l++; } int id=ask[i].id; ans[id]+=ask[i].val*tree.query(1,ask[i].y); } rep(i,1,m) printf("%lld\n",ans[i]); } return 0; }