2019南京网络赛A题

在线做法

两个区间范围限制 可以考虑主席树 如果知道x1,x2范围y值的分布 在y中进行[y1,y2]的区间和查询不就行了吗 明显的主席树

#include
using namespace std;
typedef long long ll;
const int maxn=100010;
struct node
{
    int x,y,ans;
    bool friend operator<(node f1,node f2)
    {
        return f1.x<f2.x;
    }
}a[maxn];
int X[maxn],Y[maxn];
int nodeNum;
int L[maxn<<5],R[maxn<<5],sum[maxn<<5]; 
int T[maxn]; 
int build(int l,int r) //建一个空树(所有sum[i]都为0) 
{
    int num=++nodeNum; //num为当前节点编号 
    if(l!=r)
    {
        int m=(l+r)>>1;
        L[num]=build(l,m);
        R[num]=build(m+1,r);
    }
    return num; //返回当前节点的编号 
}
int update(int pre,int l,int r,int x,int k) //pre为旧树该位置节点的编号
{
    int num=++nodeNum; //新建节点的编号 
    L[num]=L[pre];R[num]=R[pre];sum[num]=sum[pre]+k;
    //该节点左右儿子初始化为旧树该位置节点的左右儿子
    //因为插入的a[i](或Hash[x])在该节点所代表的区间中 所以sum++ 
    if(l!=r)
    {
        int m=(l+r)>>1;
        if(x<=m) L[num]=update(L[pre],l,m,x,k);
        //x出现在左子树 因此右子树保持与旧树相同 修改左子树 
        else R[num]=update(R[pre],m+1,r,x,k);
    }
    return num;
}
int query(int u,int v,int l,int r,int lx,int rx) //第k小 
{
    if(lx<=l&&r<=rx)
        return sum[v]-sum[u];
    int m=(l+r)>>1;
    int ans=0;
   if(lx<=m)
    ans+=query(L[u],L[v],l,m,lx,rx);
    if(rx>m)
        ans+=query(R[u],R[v],m+1,r,lx,rx);
        return ans;
}
int main()
{
    int M;
    scanf("%d",&M);
    while(M--)
    {
        ll n;int m,q;
        nodeNum=0;
        memset(sum,0,sizeof(sum));
        memset(X,0,sizeof(X));
        memset(Y,0,sizeof(Y));
        memset(T,0,sizeof(T));
        memset(L,0,sizeof(L));
        memset(R,0,sizeof(R));
        memset(a,0,sizeof(a));
        scanf("%lld %d %d",&n,&m,&q);
        for(int i=1;i<=m;i++)
        {
            ll x,y,ans;
            scanf("%lld %lld",&x,&y);
            a[i].x=x,a[i].y=y;
            X[i]=x;Y[i]=y;
            x=x-n/2-1;y=y-n/2-1;
            ll t=max(abs(x),abs(y));
            if(x>=y)
                ans=n*n-4*t*t-2*t-x-y;
            else
                ans=n*n-4*t*t+2*t+x+y;
            ll ten=10;
           while(ans)
           {
               a[i].ans=a[i].ans+ans%ten;
               ans/=ten;
           }
        }
        sort(X+1,X+1+m);
        sort(Y+1,Y+1+m);
        sort(a+1,a+1+m);
        int size=m;
        T[0]=build(1,size);
        for(int i=1;i<=m;i++)
        {
            int x=lower_bound(Y+1,Y+1+m,a[i].y)-Y;
            T[i]=update(T[i-1],1,size,x,a[i].ans);
        }
        while(q--)
        {
           int x1,y1,x2,y2;
            scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
            int l=lower_bound(X+1,X+1+m,x1)-X-1,r=upper_bound(X+1,X+1+m,x2)-X-1;
            printf("%d\n",query(T[l],T[r],1,size,lower_bound(Y+1,Y+1+m,y1)-Y,upper_bound(Y+1,Y+1+m,y2)-Y-1));
        }
    }
}

你可能感兴趣的:(在线做法,主席树)