zoukankan      html  css  js  c++  java
  • 【洛谷P5105】不强制在线的动态快速排序【线段树】

    题目大意:

    题目链接:https://www.luogu.org/problem/P5105
    维护两个操作:

    • 1 l r1 l r,在序列中插入[l,r][l,r]中的所有整数
    • 22,将序列排序后输出i=2lena[i]2a[i1]2⨁^{len}_{i=2}a[i]^2-a[i-1]^2

    思路:

    这道题中虽然允许元素的重复,但是显然重复的元素对答案的贡献为0。所以我们可以不用考虑元素重复的情况。
    又由于每次加入的元素是一个连续的区间,所以我们可以考虑维护一棵权值线段树。那么每次询问就把这个区间打上lazylazy标记。
    那么如何计算这个区间的贡献呢?我们可以利用这个区间连续的特性。因为x2(x1)2=(xx+1)(x+x1)=2x1x^2-(x-1)^2=(x-x+1)(x+x-1)=2x-1必然是奇数,所以我们就是要求若干连续奇数的异或和。
    打表就不难发现,从1开始,每四个连续的奇数亦或起来为0。所以这样就可以快速算出前缀异或和。

    ll xorsum(ll x)  //1 xor 3 xor ... xor x
    {
        int k=(x/2+1)%4;  //计算出这是第几个奇数
        if (k==0) return 0;
        if (k==1) return x;
    	if (k==2) return x^(x-2);
    	if (k==3) return x^(x-2)^(x-4);
    }
    

    然后区间合并的时候将这两个区间的最值用a[i]2a[i1]2a[i]^2-a[i-1]^2求出来异或进去即可。
    线段树要动态开点。
    时间复杂度O(nlogn)O(nlog n)


    代码:

    #include <cstdio>
    using namespace std;
    typedef long long ll;
    
    const int N=300010;
    int T,opt,tot,root,l,r;
    
    struct Treenode
    {
    	ll ans,maxn,minn;
    	int lc,rc;
    	bool lazy;
    };
    
    ll xorsum(ll x)
    {
        int k=(x/2+1)%4;
        if (k==0) return 0;
        if (k==1) return x;
    	if (k==2) return x^(x-2);
    	if (k==3) return x^(x-2)^(x-4);
    }
    
    struct Tree
    {
    	Treenode tree[N*64];
    	
    	void update(int x)
    	{
    		tree[x].ans=tree[tree[x].lc].ans^tree[tree[x].rc].ans;
    		if (tree[x].lc && tree[x].rc)
    			tree[x].ans^=tree[tree[x].rc].minn*tree[tree[x].rc].minn-tree[tree[x].lc].maxn*tree[tree[x].lc].maxn;
    		if (tree[x].lc)	tree[x].minn=tree[tree[x].lc].minn;
    			else tree[x].minn=tree[tree[x].rc].minn;
    		if (tree[x].rc)	tree[x].maxn=tree[tree[x].rc].maxn;
    			else tree[x].maxn=tree[tree[x].lc].maxn;
    	}
    	
    	void pushdown(int x,int l,int r)
    	{
    		if (tree[x].lazy)
    		{
    			if (!tree[x].lc) tree[x].lc=++tot;
    			if (!tree[x].rc) tree[x].rc=++tot;
    			tree[tree[x].lc].lazy=tree[tree[x].rc].lazy=1;
    			tree[x].lazy=0;
    			int mid=(l+r)>>1;
    			tree[tree[x].lc].minn=l; tree[tree[x].lc].maxn=mid;
    			tree[tree[x].rc].minn=mid+1; tree[tree[x].rc].maxn=r;
    			tree[tree[x].lc].ans=xorsum(tree[tree[x].lc].maxn*2-1)^xorsum(tree[tree[x].lc].minn*2-1);
    			tree[tree[x].rc].ans=xorsum(tree[tree[x].rc].maxn*2-1)^xorsum(tree[tree[x].rc].minn*2-1);
    		}
    	}
    	
    	void insert(int &x,int nowl,int nowr,int l,int r)
    	{
    		if (l>r) return;
    		if (!x) x=++tot;
    		if (nowl==l && nowr==r)
    		{
    			tree[x].ans=xorsum(r+r-1)^xorsum(l+l-1);
    			tree[x].maxn=r; tree[x].minn=l;
    			tree[x].lazy=1;
    			return;
    		}
    		pushdown(x,nowl,nowr);
    		int mid=(nowl+nowr)>>1;
    		if (r<=mid) insert(tree[x].lc,nowl,mid,l,r);
    		else if (l>mid) insert(tree[x].rc,mid+1,nowr,l,r);
    		else insert(tree[x].lc,nowl,mid,l,mid),insert(tree[x].rc,mid+1,nowr,mid+1,r);
    		update(x);
    	}
    }t;
    
    int main()
    {
    	scanf("%d",&T);
    	while (T--)
    	{
    		scanf("%d",&opt);
    		if (opt==1)
    		{
    			scanf("%d%d",&l,&r);
    			t.insert(root,1,1e9,l,r);
    		}
    		else printf("%lld
    ",t.tree[1].ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    SAP S/4HANA extensibility扩展原理介绍
    SAP CRM系统订单模型的设计与实现
    使用nodejs代码在SAP C4C里创建Individual customer
    SAP Cloud for Customer Account和individual customer的区别
    Let the Balloon Rise map一个数组
    How Many Tables 简单并查集
    Heap Operations 优先队列
    Arpa’s obvious problem and Mehrdad’s terrible solution 思维
    Passing the Message 单调栈两次
    The Suspects 并查集
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998057.html
Copyright © 2011-2022 走看看