• luogu P6627 【[省选联考 2020 B 卷] 幸运数字】|标记永久化线段树


    退役选手来写篇题解

    把三种条件全部转化成区间修改

    线段树离散化后维护一下

    1.就相当与([L,R])异或上 (x)

    2.相当于一个区间([A,A])异或上 (x)

    3.相当于两个区间([-1e9,B-1],[B+1,1e9])异或上 (x)

    根据求答案的绝对值最小,绝对值相同取正数的原则

    先把 (0,1e9,-1e9) 这些边界加入到离散化数组里

    1.把 (L-1,L,R-1,R) 计入答案考虑

    2.把 (A-1,A,A+1) 计入答案考虑

    3.把 (B-1,B,B-1) 计入答案考虑

    可以证明最优答案不会出现在这些点以外的地方


    提供一个简要而且不那么严谨的证明

    对于一个异或值相同的区间([L,R])

    如果答案为此异或值,那么答案只会有三种情况

    (L) ((0<L<R))

    (0) ((L<0<R))

    (R) ((L<R<0))

    根据我们的区间转化原则,有可能存在

    对于一个异或值相同的是多个区间([L1,R1][L2,R2]..)

    那也可以把他们认为成独立的多个区间,答案一定也是里面的子集


    细节问题可以看代码

    本人退役选手,菜的一批

    我省选写这题的时候就是数组开小了,应该开(4n)长度的线段树

    所以这题我考的时候只有35分

    很多东西是个人理解,要是说错了什么地方,望告知

    #include<vector>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define int long long
    #define lb lower_bound
    #define pb push_back
    inline int read(){
    	int x=0,f=1; char c=getchar();
    	while(c<'0'||c>'9'){ if(c=='-')f=-1; c=getchar(); }
    	while('0'<=c&&c<='9'){ x=(x<<3)+(x<<1)+(c^48); c=getchar(); }
    	return x*f;
    }
    const int N=1e6+10;
    struct Seg{
    	int l,r,sum;
    	#define l(x) tree[x].l
    	#define r(x) tree[x].r
    	#define sum(x) tree[x].sum
    }tree[N<<2];
    #define ls p<<1
    #define rs p<<1|1
    #define mid ((l(p)+r(p))>>1)
    void build(int p,int l,int r){
    	l(p)=l,r(p)=r;
    	if(l(p)==r(p))return;
    	build(ls,l,mid);
    	build(rs,mid+1,r);
    }
    void update(int p,int l,int r,int d){
    	if(l<=l(p)&&r(p)<=r){ sum(p)^=d; return; }
    	if(l<=mid)update(ls,l,r,d);
    	if(r>mid)update(rs,l,r,d);
    }
    int ans[N<<2];
    void query(int p,int d){
    	d^=sum(p);
    	if(l(p)==r(p)){ ans[l(p)]=d; return; }
    	query(ls,d),query(rs,d);
    }
    int b[N<<2],len;
    struct node{
    	int t,l,r,w,x;
    }e[N];
    vector<int>sxr;
    signed main(){
    	int n=read();
    	b[++len]=-1e9; b[++len]=0; b[++len]=1e9;
    	for(int i=1,t,l,r,w,x;i<=n;i++){
    		t=read();
    		if(t==1){
    			l=read(),r=read(),w=read();
    			b[++len]=l,b[++len]=r;
    			b[++len]=l-1,b[++len]=r+1;
    		}else{
    			x=read(),w=read();
    			b[++len]=x;
    			b[++len]=x-1;
    			b[++len]=x+1;
    		}
    		e[i]=(node){t,l,r,w,x};
    	}
    	sort(b+1,b+1+len);
    	len=unique(b+1,b+1+len)-b-1;
    	build(1,1,len);
    	for(int i=1,t,l,r,w,x;i<=n;i++){
    		t=e[i].t;
    		if(t==1){
    			l=e[i].l,r=e[i].r,w=e[i].w;
    			l=lb(b+1,b+1+len,l)-b;
    			r=lb(b+1,b+1+len,r)-b;
    			update(1,l,r,w);
    		}else if(t==2){
    			x=e[i].x,w=e[i].w;
    			x=lb(b+1,b+1+len,x)-b;
    			update(1,x,x,w);
    		}else if(t==3){
    			x=e[i].x,w=e[i].w;
    			x=lb(b+1,b+1+len,x)-b;
    			if(x>1)update(1,1,x-1,w);
    			if(x<len)update(1,x+1,len,w);
    		}
    	}
    	query(1,0);
    	int Ans=0;
    	for(int i=1;i<=len;i++)
    	if(ans[i]>Ans){
    		Ans=ans[i];
    		sxr.clear();
    		sxr.pb(b[i]);
    	}else if(ans[i]==Ans)sxr.pb(b[i]);
    	printf("%lld ",Ans);
    	Ans = -(1ll<<62);
    	for(int i=0;i<sxr.size();i++){
    		if(abs(sxr[i])<abs(Ans))Ans=sxr[i];
    		else if(abs(sxr[i])==abs(Ans))Ans=max(Ans,sxr[i]);
    	}
    	printf("%lld
    ",Ans);
    }
    
  • 相关阅读:
    内核驱动系列中断和定时器
    apue2 阅读笔记第四章
    apue2 阅读笔记 第五章
    apue2阅读笔记 第6.7章
    再试试windows7版得writer
    内核驱动系列内核调试方法
    apue2 阅读笔记第三章
    杂谈关于代码库
    know everything about something
    React的父子传值(父传子)
  • 原文地址:https://www.cnblogs.com/naruto-mzx/p/13198638.html
Copyright © 2020-2023  润新知