您的位置:首页 > 其它

CF 853-C

2017-10-04 15:46 141 查看

CF 853-C

主席树

http://codeforces.com/problemset/problem/853/C

题解:

选择的矩形的四条边延长,将整个平面分成9块。

求出这9块中各自有多少点,分情况讨论即可。

二维前缀和MLE?上主席树啦~

Code:

#include <iostream>
#include <cstring>
#include <cstdio>
#define D(x) cout<<#x<<" = "<<x<<"  "
#define E cout<<endl
using namespace std;
const int N = 300005;
int lch[N*30],rch[N*30],num[N*30],root
,sz,n,q,mark
;

void clone(int x,int t){
lch[x]=lch[t]; rch[x]=rch[t]; num[x]=num[t];
}

void ins(int &x,int t,int l,int r,int p){
x=++sz; clone(x,t); num[x]++;
if(l==r) return;
int mid=(l+r)>>1;
if(p<=mid) ins(lch[x],lch[t],l,mid,p);
else ins(rch[x],rch[t],mid+1,r,p);
}

int query(int a,int b,int l,int r,int ql,int qr){
if(ql<=l && r<=qr) return num[b]-num[a];
else{
int mid=(l+r)>>1, ans=0;
if(ql<=mid) ans+=query(lch[a],lch[b],l,mid,ql,qr);
if(qr>mid) ans+=query(rch[a],rch[b],mid+1,r,ql,qr);
return ans;
}
}

long long count(int l,int d,int r,int u){
if(l>r || d>u) return 0;
int res=query(root[d-1],root[u],1,n,l,r);
return 1LL*(res-1)*res/2LL;
}

int main(){
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++) scanf("%d",mark+i);
for(int i=1;i<=n;i++) ins(root[i],root[i-1],1,n,mark[i]);
while(q--){
int l,d,r,u;
scanf("%d%d%d%d",&d,&l,&u,&r);
long long ans=1LL*(n-1)*n/2LL;
ans-=count(1,1,l-1,n);
ans-=count(r+1,1,n,n);
ans-=count(1,1,n,d-1);
ans-=count(1,u+1,n,n);
ans+=count(1,1,l-1,d-1);
ans+=count(r+1,1,n,d-1);
ans+=count(1,u+1,l-1,n);
ans+=count(r+1,u+1,n,n);
printf("%lld\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: