zoukankan      html  css  js  c++  java
  • zoj 3633 ——线段树

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3633

    给你n个数,然后m个询问,每次询问区间[a,b]中从右到左最先出现重复的数字,比如

    5
    1 2 3 1 2

    询问[1 5],那么答案就是2.因为2是第一次出现2次的。其中 3≤ n ≤ 500,000,1 ≤ m ≤ 50,000,数值<=2^31-1。

    解法是,先把所有数字从小到大排序,相同的按出现的先后顺序排序。

    更新时,对于每一个数x,如果前面的y==x的话,那么在线段树中,在x的坐标位置上赋值上y的坐标位置。

    查询时,[a,b]就是查询区间[a,b]中大于等于a的最大值。如果最大值都小于a,那么就说明没有重复的。

    比如上面的数据1 2 3 1 2,排序后就是:

            1  1  2  2  3

    pos:1  4  2  5  3

    那么线段树中,[4,4]的值就是1,[5,5]的值就是2。其他线段没有值。

    那么我们查询[1,4]的时候,显然最大值就是1,1大于等于[1,4]中的1,这就说明了有重复。因为线段[4,4]的值1实际上就说明了,原来在下标1到下标4有重复的数出现了。

    还不清楚的话我们可以再试试查询区间[2,4],线段[2,4]在线段树上的最大值还是1,它小于2,没有重复。

    这里说明了,[1,4]有重复的话,如果我们想要得到一个重复的区间,那么我们查询区间的左边界一定要小于等于1才有可能,这也是[2,4]没有重复区间的原因。

    View Code
      1 #include<iostream>
      2 #include<string>
      3 #include<stdio.h>
      4 #include<memory.h>
      5 #include<algorithm>
      6 using namespace std;
      7 int max(int a,int b){return a>b?a:b;}
      8 
      9 struct node
     10 {
     11     int l;
     12     int r;
     13     int val;
     14 };
     15 
     16 struct Point
     17 {
     18     int pos;
     19     int val;
     20 };
     21 
     22 Point x[500001];
     23 int n;
     24 node tree[2500000];
     25 int X[500001];
     26 
     27 void build(int i,int l,int r)
     28 {
     29     tree[i].l=l;
     30     tree[i].r=r;
     31     tree[i].val=0;
     32     if(l==r)
     33         return;
     34     int mid=(l+r)/2;
     35     build(2*i,l,mid);
     36     build(2*i+1,mid+1,r);
     37 }
     38 
     39 void updata(int i,int l,int r,int w)
     40 {
     41     if(tree[i].l>r || tree[i].r<l)
     42         return;
     43     if(tree[i].l>=l && tree[i].r<=r)
     44     {
     45         tree[i].val=w;
     46         return;
     47     }
     48     updata(2*i,l,r,w);
     49     updata(2*i+1,l,r,w);
     50     tree[i].val=max(tree[2*i].val,tree[2*i+1].val);
     51 }
     52 
     53 int ans;
     54 void find(int i,int l,int r)
     55 {
     56     if(tree[i].l>r || tree[i].r<l)
     57         return;
     58     if(tree[i].l>=l && tree[i].r<=r)
     59     {
     60         ans=max(ans,tree[i].val);
     61         return;
     62     }
     63     find(2*i,l,r);
     64     find(2*i+1,l,r);
     65 }
     66 
     67 int cmp(Point a,Point b)
     68 {
     69     if(a.val!=b.val)
     70         return a.val<b.val;
     71     else
     72         return a.pos<b.pos;
     73 }
     74 
     75 int main()
     76 {
     77     int i,a,b,m;
     78     freopen("D:\\in.txt","r",stdin);
     79     while(scanf("%d",&n)==1)
     80     {
     81         for(i=0;i<n;i++)
     82         {
     83             scanf("%d",&x[i].val);
     84             X[i+1]=x[i].val; //保护原始数据的顺序
     85             x[i].pos=i+1;
     86         }
     87         build(1,1,n);
     88         sort(x,x+n,cmp);
     89         for(i=1;i<n;i++)
     90         {
     91             if(x[i].val==x[i-1].val)
     92             {
     93                 updata(1,x[i].pos,x[i].pos,x[i-1].pos);
     94             }
     95         }
     96         scanf("%d",&m);
     97         while(m--)
     98         {
     99             scanf("%d%d",&a,&b);
    100             ans=0;
    101             find(1,a,b);
    102             if(ans<a)
    103                 printf("OK\n");
    104             else
    105                 printf("%d\n",X[ans]);
    106         }
    107         printf("\n");
    108     }
    109     return 0;
    110 }
  • 相关阅读:
    标题栏外区域拖动窗体
    搜索引擎技术核心揭密
    用C#实现木马程序(转载)
    DotNet里的控件数组
    RECORDNUMBER应用之控制每页显示行数及隔行换色
    搜索引擎技术学习
    VB里面操作Excel(居然比C#强)
    第三代搜索引擎技术与P2P
    C# 用API播放声音
    如何判断ExecuteScalar()得到的结果是否有记录
  • 原文地址:https://www.cnblogs.com/ka200812/p/2657662.html
Copyright © 2011-2022 走看看