• bzoj 2989: 数列


    LINK:数列

    需要动一点脑子 考虑查询 暴力显然不行 考虑把绝对值拆开。

    当x<=y ax<=ay时 有 y-x+ay-ax<=k x+ax>=y+ay-k 可以发现在满足前两个条件下第三个条件是这样才会被统计贡献。

    剩下3种情况分别是 x+ax<=k+ay+y x-ax<=k+y-ay ax-x=k-y+ay

    可以发现 这个类似于三维偏序问题 我们进行三维数点即可 但是由于操作有时间关系 上CDQ的话就变成了四维偏序。

    直接KD tree即可。考虑修改操作 其实就是插入 由于历史版本还有我们不需要删除。

    考虑替罪羊树维护。

    //#include<bitsstdc++.h>
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<ctime>
    #include<cmath>
    #include<cctype>
    #include<cstdlib>
    #include<queue>
    #include<deque>
    #include<stack>
    #include<vector>
    #include<algorithm>
    #include<utility>
    #include<bitset>
    #include<set>
    #include<map>
    #define ll long long
    #define db double
    #define INF 1000000000
    #define ld long double
    #define pb push_back
    #define get(x) x=read()
    #define gt(x) scanf("%d",&x)
    #define put(x) printf("%d
    ",x)
    #define rep(p,n,i) for(RE int i=p;i<=n;++i)
    #define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
    #define pii pair<int,int> 
    #define F first
    #define S second
    #define mk make_pair
    #define mod 1000000007
    #define RE register
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
    	return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
    	RE int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	return x*f;
    }
    const db alpha=0.75;
    const int MAXN=110000;
    const int K=3;
    int n,Q,cnt,D,top,ans,root;
    char a[10];
    struct wy
    {
    	int l,r;
    	int mx[K],mn[K];
    	int d[K];//自己本身元素
    	int sum;
    }t[MAXN<<2];
    int q[MAXN<<2],b[MAXN];
    inline int cmp(int a,int b){return t[a].d[D]<t[b].d[D];}
    inline void pushup(int p)
    {
    	int l=t[p].l;int r=t[p].r;
    	t[p].sum=t[l].sum+t[r].sum+1;
    	rep(0,K-1,i)
    	{
    		if(l)t[p].mx[i]=max(t[l].mx[i],t[p].mx[i]),t[p].mn[i]=min(t[p].mn[i],t[l].mn[i]);
    		if(r)t[p].mx[i]=max(t[r].mx[i],t[p].mx[i]),t[p].mn[i]=min(t[p].mn[i],t[r].mn[i]);
    	}
    }
    inline int build(int l,int r,int k)
    {
    	if(l>r)return 0;
    	int mid=(l+r)>>1;D=k;
    	nth_element(q+l,q+mid,q+1+r,cmp);
    	rep(0,K-1,i)t[q[mid]].mx[i]=t[q[mid]].mn[i]=t[q[mid]].d[i];
    	t[q[mid]].l=build(l,mid-1,(k+1)%K);
    	t[q[mid]].r=build(mid+1,r,(k+1)%K);
    	pushup(q[mid]);return q[mid];
    }
    inline void dfs(int x)
    {
    	if(!x)return;
    	q[++top]=x;
    	if(t[x].l)dfs(t[x].l);
    	if(t[x].r)dfs(t[x].r);
    }
    inline void insert(int &p,int x,int k,int flag)
    {
    	if(!p)
    	{
    		p=x;t[p].sum=1;
    		rep(0,K-1,i)t[p].mx[i]=t[p].mn[i]=t[p].d[i];
    		return;
    	}
    	int mark=0;
    	if(t[x].d[k]<t[p].d[k])
    	{
    		if(t[t[p].l].sum>=t[p].sum*alpha)mark=1;
    		insert(t[p].l,x,(k+1)%K,flag|mark);
    	}
    	else
    	{
    		if(t[t[p].r].sum>=t[p].sum*alpha)mark=1;
    		insert(t[p].r,x,(k+1)%K,flag|mark);
    	}
    	if(mark&&!flag)top=0,dfs(p),p=build(1,top,k);
    	else pushup(p);
    }
    inline int check(int x)
    {
    	rep(0,K-1,i)if(t[x].mx[i]>q[i])return 0;
    	return 1;
    }
    inline int check_point(int x)
    {
    	rep(0,K-1,i)if(t[x].d[i]>q[i])return 0;
    	return 1;
    }
    inline int check_range(int x)
    {
    	rep(0,K-1,i)if(t[x].mn[i]>q[i])return 0;
    	return 1;
    }
    inline void ask(int x)
    {
    	if(check(x)){ans+=t[x].sum;return;}
    	if(check_point(x))++ans;
    	if(t[x].l&&check_range(t[x].l))
    		ask(t[x].l);
    	if(t[x].r&&check_range(t[x].r))
    		ask(t[x].r);
    }
    int main()
    {
    	freopen("1.in","r",stdin);
    	get(n);get(Q);
    	rep(1,n,i)
    	{
    		int x;get(x);b[i]=x;
    		t[++cnt].d[0]=i;t[cnt].d[1]=x;t[cnt].d[2]=-i-x;q[cnt]=cnt;
    		t[++cnt].d[0]=-i;t[cnt].d[1]=-x;t[cnt].d[2]=i+x;q[cnt]=cnt;
    		t[++cnt].d[0]=-i;t[cnt].d[1]=x;t[cnt].d[2]=i-x;q[cnt]=cnt;
    		t[++cnt].d[0]=i;t[cnt].d[1]=-x;t[cnt].d[2]=x-i;q[cnt]=cnt;
    	}
    	root=build(1,cnt,0);
    	rep(1,Q,i)
    	{
    		scanf("%s",a+1);
    		if(a[1]=='M')
    		{
    			int x,y;get(x);get(y);b[x]=y;
    			t[++cnt].d[0]=x;t[cnt].d[1]=y;t[cnt].d[2]=-x-y;insert(root,cnt,0,0);
    			t[++cnt].d[0]=-x;t[cnt].d[1]=-y;t[cnt].d[2]=y+x;insert(root,cnt,0,0);
    			t[++cnt].d[0]=-x;t[cnt].d[1]=y;t[cnt].d[2]=x-y;insert(root,cnt,0,0);
    			t[++cnt].d[0]=x;t[cnt].d[1]=-y;t[cnt].d[2]=y-x;insert(root,cnt,0,0);
    		}
    		else
    		{
    			ans=0;int x,y;get(x);get(y);
    			//x<=y ax<=ay -x-ax<=-y-ay+k 也统计x相等y相等
    			q[0]=x;q[1]=b[x];q[2]=-x-b[x]+y;ask(root);
    			//x>=y ax>ay x+ax<=k+ay+y
    			q[0]=-x;q[1]=-b[x]-1;q[2]=x+b[x]+y;ask(root);
    			//x>y ax<=ay x-ax<=k+y-ay
    			q[0]=-x-1;q[1]=b[x];q[2]=y+x-b[x];ask(root);
    			//x<y ax>=ay -x+ax<=k+ay-y;
    			q[0]=x-1;q[1]=-b[x];q[2]=y+b[x]-x;ask(root);
    			put(ans);
    		}
    	}
    	return 0;
    }
    

    代码写的有问题 我这样做应该建立四棵KD-tree。

    或者 写四个ask 我觉得。

    网上题解都是旋转坐标系转契比雪夫距离了。我思考一下我这种做法对不对。

  • 相关阅读:
    1104 Sum of Number Segments (20 分)(数学问题)
    1092 To Buy or Not to Buy (20 分)(hash散列)
    1082 Read Number in Chinese (25 分)(字符串处理)【背】
    1105 Spiral Matrix (25 分)(模拟)
    初识网络安全及搭建网站(内网)
    HTML5开发者需要了解的技巧和工具汇总(转)
    native+web开发模式之web前端经验分享
    移动平台3G手机网站前端开发布局技巧汇总(转)
    Asp.net 中图片存储数据库以及页面读取显示通用方法详解附源码下载
    使用H3Viewer来查看VS2010的帮助文档
  • 原文地址:https://www.cnblogs.com/chdy/p/12533032.html
Copyright © 2020-2023  润新知