zoukankan      html  css  js  c++  java
  • 洛谷P1972 【[SDOI2009]HH的项链】

    这道题想了很久,发题解是为了理解的更深刻一点。。。(管理放我过好嘛qwq)


    步入正题:这道题应该是很多做法,我选择的是离线+树状数组。

    首先输入数组。用fisrt数组先记录元素最开始出现的位置,对应的每一个树状数组的位置add一下(树状数组洛谷也有模板题的了解一下就ok啦)。

    rep(i,1,n){//for循环的意思(1,n)闭区间
            scanf("%d",&a[i]);
            if(!first[a[i]]){
                first[a[i]]=i;
                add(i);//若第一次出现 则在树状数组中add。
            }
        }
    

    然后倒着更新一遍数组,对每个元素用last数组记录当前下标元素的下一个出现的位置(可以模拟一遍就理解了)

    per(i,n,1){//还是for循环(n,1)
            last[i]=first[a[i]];
            first[a[i]]=i;//last数组记录当前元素 下一次出现的位置。
        }
    

    接下来就是存一下询问啦。用vector存结构体应该快一点,结构体用左端点为关键字进行sort排序。

        struct uzi{//全局的结构体,id为询问的序号
            int x,y,id;
            bool operator <(const uzi &a)const{
                return x<a.x;
             } 
        };
    
    	vector<uzi> val;
        rep(i,0,m-1){
            int x,y;
            scanf("%d%d",&x,&y);
            val.push_back(uzi{x,y,i});//将询问存入
        }
        sort(val.begin(),val.end());//排序
    

    接下来就是询问的处理啦(jd)

    因为已经按左端点排序好了,所以 直接对树状数组动态更新,然后记录答案。这里用了一个j。当j比左端点小,就在j下标元素下个出现的位置对树状数组更新。(add)。。然后记录询问的结果就好啦。。。

    for(auto k:val){
            while(j<k.x){
                add(last[j]);
                j++;
            }
            ans[k.id]=sum(k.y)-sum(k.x-1);
        }
    

    然后直接输出每个询问的结果就做完啦。。。。。
    贴下全部的代码


    #include<bits/stdc++.h>
    #define swap(a,b) {a^=b;b^=a;a^=b}
    #define rep(a,b,c) for(int a=b;a<=c;a++)
    #define per(i,n,a) for (int i=n;i>=a;i--)
    #define max(a,b) (a)>(b)?(a):(b)
    #define min(a,b) (a)<(b)?(a):(b)
    #define PII pair<int,int>
    #define yxdl(qt) priority_queue<int,vector<int>,greater<int> >qt
    #define xgd(qt)  priority_queue<int,vector<int>,less<int> >qt
    #define INF 0x3f3f3f3f
    #define lowbit(x)  x & -x
    #define cs(s) freopen(s,"r",stdin)
    #define debug(x) printf(" case-->%d ",x );
    using namespace std;
    typedef long long ll;
    int a[500010],tree[500011],first[5000101],last[5100001],n,m,ans[510001];
    struct uzi{
        int x,y,id;
        bool operator <(const uzi &a)const{
         	return x<a.x;
         } 
    };
    inline void add(int x){for(int i=x;i<=n;i+=lowbit(i))tree[i]+=1;}
    inline int sum (int x){int ans=0;for(int i=x;i;i-=lowbit(i))ans+=tree[i];return ans;}
    int main(){
        scanf("%d",&n);	
        rep(i,1,n){
            scanf("%d",&a[i]);
            if(!first[a[i]]){
                first[a[i]]=i;
                add(i);//若第一次出现 则在树状数组中add。
            }
        }
        per(i,n,1){
            last[i]=first[a[i]];
            first[a[i]]=i;//last数组记录当前元素 下一次出现的位置。
        }	
        scanf("%d",&m);
        vector<uzi> val;
        rep(i,0,m-1){
            int x,y;
            scanf("%d%d",&x,&y);
            val.push_back(uzi{x,y,i});//将询问存入
        }
        int j=1;
        sort(val.begin(),val.end());//排序
        for(auto k:val){
            while(j<k.x){
                add(last[j]);
                j++;
            }
            ans[k.id]=sum(k.y)-sum(k.x-1);
        }
        rep(i,0,m-1){
            printf("%d
    ",ans[i] );
        }
    }
    
    
  • 相关阅读:
    【转载】总结一下Android中主题(Theme)的正确玩法
    Android获唯一标识
    AS问题解决系列3—iCCP: Not recognizing known sRGB profile
    AS问题解决系列1—Unable to execute DX错误
    Android Studio Error2
    Android Error
    NAT简单介绍
    redis缓存工具Jedis进行跨jvm加锁(分布式应用)--不幸暂弃用--能够做第三方锁使用
    工作总结1.怎样高效跟客户确定需求?
    Sqoop处理Clob与Blob字段
  • 原文地址:https://www.cnblogs.com/pubgoso/p/10759737.html
Copyright © 2011-2022 走看看