zoukankan      html  css  js  c++  java
  • One Occurrence [CodeForces1000F]

    题目传送门

    这个题目有多种写法

    1.线段树动态更新与查找
    pos[i]记录位置i上出现的数上次出现的位置。将询问按右区间排序。

    从1到n扫,把线段树上pos[i]的值改成INF,
    比如 1 1 ,线段树原来是 0 1 ,扫完第二个 1 后,线段树变成 INF 1,那么查找的时候,查找 L到 R之内最小的那个值,注意最后还要判断这个最小值是不是比L还要小。

    code:

    
    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define File(x) freopen("(x)","r",stdin)
    #define pf printf
    #define ull unsigned long long
    #define db double
    #define ll long long
    const int  MAXN=5e5+10;
    #define MAXM 
    #define P 
    
    int T, n, m, l, r, siz, lim, bol[MAXN], ans[MAXN], t[MAXN], a[MAXN],as;
    
    struct Q {int l, r, x, y, id;} q[MAXN]; 
     
    
    bool CMP(Q x, Q y)
    {
         return x.r<y.r;  
    }
    
    int pos[MAXN],la[MAXN],lw[MAXN],pr[MAXN],mn[MAXN<<2],num[MAXN<<2];
    
    void build(int u,int L,int R,int ps){
        if(L==R){ 
            mn[u]=pos[ps];
            return;
        }
        int lson=u<<1,rson=u<<1|1,mid=L+R>>1;
        if(ps<=mid)
        build(lson,L,mid,ps);
        else
        build(rson,mid+1,R,ps);
        mn[u]=min(mn[lson],mn[rson]);
    }
    
    void upd(int u,int L,int R,int ps){ 
        if(L==R){
            mn[u]=MAXN+10000;return;
        }
        int lson=u<<1,rson=u<<1|1,mid=L+R>>1;
        if(ps<=mid)
        upd(lson,L,mid,ps);
        else
        upd(rson,mid+1,R,ps);
        mn[u]=min(mn[lson],mn[rson]);
    }
    
    int Q(int u,int L,int R,int l,int r){
        int lson=u<<1,rson=u<<1|1,mid=L+R>>1;
        int w1=0,w2=0;
        if(mn[u]>=MAXN)return 0;
    
    
      //  cout<<"Q"<<l<<" "<<r<<" "<<L<<" "<<R<<endl;
       // cout<<mn[lson]<<"&"<<mn[rson]<<" "<<mn[u]<<endl;
    
        if(L==R)return mn[u]<MAXN+1?a[L]:0;
        
        if(mn[rson]<l&&r>mid)
             if(w2=Q(rson,mid+1,R,l,r))return w2;
        if(mn[lson]<l&&l<=mid){
            if(w1=Q(lson,L,mid,l,r))return w1;  
        }
        return 0;
    }
    
    int main()
    { 
            cin>>n; 
            
            for(int i=0;i<(MAXN<<2);i++)mn[i]=MAXN+100000;
    
            for(int i=1; i<=n; ++i) {
                scanf("%d", &a[i]); 
            }
             for(int i=1; i<=n; ++i) { 
                pos[i]=la[a[i]];
                la[a[i]]=i;
            }
            
            cin>>m;
            
            for(int i=1; i<=m; ++i) {
                scanf("%d%d", &q[i].l,&q[i].r); 
                q[i].id=i;
            }
            sort(q+1, q+m+1, CMP); 
            int ps=0;
            for(int i=1; i<=m; ++i) {  
                while(ps<q[i].r){
                    ++ps;
                    build(1,1,n,ps);  
                    if(pos[ps]>0){ 
                        upd(1,1,n,pos[ps]);  
                    }   
                }
                ans[q[i].id]=Q(1,1,n,q[i].l,q[i].r);
            }
            for(int i=1; i<=m; ++i) printf("%d
    ", ans[i]); 
    }
    
    

    2.莫队

    注意数据集合的增和删。用一个stack,增就直接入栈,删就把栈顶放到这个数原来的位置。(可以记录每个数在栈位置).注意这份代码会T。
    T——T

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define File(x) freopen("(x)","r",stdin)
    #define pf printf
    #define ull unsigned long long
    #define db double
    #define ll long long
    const int  MAXN=5e5+10;
    #define MAXM 
    #define P 
    
    int T, n, m, l, r, siz, lim, bol[MAXN], ans[MAXN], t[MAXN], num[MAXN], a[MAXN],as;
    struct Q {int l, r, x, y, id;} q[MAXN]; 
     int stk[MAXN],top=0,pos[MAXN];
    void add(int x, int k)
    {
       // cout<<x<<"-"<<k<<endl;
        if(k==1)stk[++top]=x,pos[x]=top;
        else{
            pos[stk[top]]=pos[x];
            stk[pos[x]]=stk[top];
            --top;
        }
    }
     
    
    bool CMP(Q x, Q y)
    {
        if(bol[x.l]==bol[y.l]) {
            if(bol[x.l]&1) return x.r<y.r;
            else return x.r>y.r;
        }
        return x.l<y.l;
    }
    
    int main()
    { 
            cin>>n;
            l=1, r=0, lim=0, siz=max(1, (int)sqrt(n)); 
            for(int i=1; i<=5e5+5; ++i) num[i]=t[i]=0;
            for(int i=1; i<=n; ++i) {
                scanf("%d", &a[i]); 
                bol[i]=(i-1)/siz+1;
            }
    
            cin>>m;
            
            for(int i=1; i<=m; ++i) {
                scanf("%d%d", &q[i].l,&q[i].r); 
                q[i].id=i;
            }
    
            sort(q+1, q+m+1, CMP);
            
            for(int i=1; i<=m; ++i) {  
                while(r<q[i].r) {//jiaru
                    r++;
                    if(!num[a[r]]) add(a[r], 1);
                    else {
                        if(num[a[r]]==1)
                        add(a[r],-1);
                    }
                    num[a[r]]++;
                }
                while(r>q[i].r) {//tichu
                    num[a[r]]--;
                    if(num[a[r]]==1) add(a[r], 1);
                    else if(num[a[r]]==0)add(a[r],-1);
                    r--;
                }
                while(l<q[i].l) {//tichu 
                    num[a[l]]--; 
                    if(!num[a[l]]) add(a[l], -1);
                    if(num[a[l]]==1)add(a[l],1);
                    l++;
                }
                while(l>q[i].l) {//jiaru
                    l--;
                    if(!num[a[l]]) add(a[l], 1);
                    else if(num[a[l]]==1)add(a[l],-1);
                    num[a[l]]++;
                }  
                ans[q[i].id]=stk[top];
            }
            for(int i=1; i<=m; ++i) printf("%d
    ", ans[i]); 
    }
    
    
  • 相关阅读:
    欧几里得算法及扩展欧几里得(含)
    RP
    P1734_最大约数和
    The 2017 ACM-ICPC Asia East Continent League Final记录
    【数据结构】bzoj1651专用牛棚
    【数据结构】bzoj1455罗马游戏
    【数据结构】bzoj1636/bzoj1699排队
    【数据结构】bzoj3747Kinoman
    【计算几何】奇特的门
    Topcoder SRM 608 div1 题解
  • 原文地址:https://www.cnblogs.com/GUOGaby/p/15050205.html
Copyright © 2011-2022 走看看