2019CCPC网络赛——array(权值线段树)

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=6703

题目大意:

给出一个n(n<1e5)个元素的数组A,A中所有元素都是不重复的[1,n]。

有两种操作:

1.将pos位置的元素+1e7

2.查询不属于[1,r]中的最小的>=k的值。

强制在线,上次计算结果和输入值xor得到区间。

比赛的时候感觉这道题有点线段树的感觉,和前段时间多校训练一个题很像,想了40多分钟才理想清思路。

 

解法:

  可以看出,执行1操作的时候加的数非常大,可以得出每次输出的答案在为1到n+1之间。可以将1-n的每个数在数组A中的位置记录下,存在线段树中,维护线段树区间最大值。

  当执行2操作时,只需要查询区间[k,n]中大于r的值即可,找出最小的数字,先搜索左子树,若无答案搜索右子树,若两侧均无解则答案为n+1。

  当执行1操作时,由于pos+1e7,因此之后的数组中不存在该数,将第pos位的数字在线段树中的值转换为inf即可。

  贴上自己比赛时打了40多分钟的代码

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair <int,int> pii;
#define rep(i,x,y) for(int i=x;i<y;i++)
#define rept(i,x,y) for(int i=x;i<=y;i++)
#define per(i,x,y) for(int i=x;i>=y;i--)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define de(x) cout<< #x<<" = "<<x<<endl
#define dd(x) cout<< #x<<" = "<<x<<" "
#define mes(a,b) memset(a,b,sizeof a)
const int inf= 0x3f3f3f3f;
int arrcy[100005],p[100005];
class Tree
{
    public:
        int l,r,val;
}tree[400005];
void build(int id,int l,int r);
void change(int id,int x);
void test();
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    cin>>t;
    while(t--)
        test();
    return 0;
}
int find(int id,int r,int k);
void test()
{
    int n,q;
    int ans=0;
    cin>>n>>q;
    rept(i,1,n)
    {
        cin>>arrcy[i];
        p[arrcy[i]]=i;
    }
    build(1,1,n);
    rep(i,0,q)
    {
        int way;
        cin>>way;
        if(way==1)
        {
            int pos;
            cin>>pos;
            change(1,arrcy[ans^pos]);
        }
        else
        {
            int r,k;
            cin>>r>>k;
            r^=ans;
            k^=ans;
    //        cout<<"r="<<r<<" "<<"k="<<k<<endl;
            ans=find(1,r,k);
            if(ans==-1)
                ans=max(n+1,k);
            cout<<ans<<endl;
        }
    }
}
void build(int id,int l,int r)
{
    tree[id].l=l;
    tree[id].r=r;
    if(l==r)
    {
        tree[id].val=p[l];
        return ;
    }
    int mid=(l+r)/2;
    build(id*2,l,mid);
    build(id*2+1,mid+1,r);
    tree[id].val=max(tree[id*2].val,tree[id*2+1].val);
}

int find(int id,int r,int k)
{
    if(tree[id].l==tree[id].r)
    {
        if(tree[id].val>r)
            return tree[id].l;
        else return -1;
    }
    int mid=(tree[id].l+tree[id].r)/2,ans=-1;
    if(mid>=k&&tree[id*2].val>r) ans=find(id*2,r,k);
    if(ans!=-1) return ans;
    else if(tree[id*2+1].r>=k&&tree[id*2+1].val>r) ans=find(id*2+1,r,k);
    return ans;
}

void change(int id,int x)//将x转换为inf
{
    if(tree[id].l==tree[id].r)
    {
        tree[id].val=inf;
        return ;
    }
    if(x<=(tree[id].l+tree[id].r)/2) change(id*2,x);
    else change(id*2+1,x);
    tree[id].val=max(tree[id*2].val,tree[id*2+1].val);
}

 

posted @ 2019-09-10 16:24  GGMU  阅读(242)  评论(0编辑  收藏  举报