Codeforces 522D Closest Equals

题解:

傻逼题

直接从左向右扫描每个点作为右端点

然后单点修改区间查询就行了

另外一种更直观的做法就是$(i,j)$之间产生了$(j-i)$

于是变成矩形查最大值,kd-tree维护

代码:

#include <bits/stdc++.h>
#define rint register int
#define IL inline
#define rep(i,h,t) for (int i=h;i<=t;i++)
#define dep(i,t,h) for (int i=t;i>=h;i--)
#define me(x) memset(x,0,sizeof(x))
#define ll long long
namespace IO{
    char ss[1<<24],*A=ss,*B=ss;
    IL char gc()
    {
        return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++;
    }
    template<class T>void read(T &x)
    {
        rint f=1,c; while (c=gc(),c<48||c>57) if (c==‘-‘) f=-1; x=(c^48);
        while (c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f;
    }
    char sr[1<<24],z[20]; int Z,C=-1;
    template<class T>void wer(T x)
    {
        if (x<0) sr[++C]=‘-‘,x=-x;
        while (z[++Z]=x%10+48,x/=10);
        while (sr[++C]=z[Z],--Z);
    }
    IL void wer1() {sr[++C]=‘ ‘;}
    IL void wer2() {sr[++C]=‘\n‘;}
    template<class T>IL void maxa(T &x,T y) {if (x<y) x=y;}
    template<class T>IL void mina(T &x,T y) {if (x>y) x=y;}
    template<class T>IL T MAX(T x,T y) { return x>y?x:y;}
    template<class T>IL T MIN(T x,T y) { return x<y?x:y;}
};
using namespace std;
using namespace IO;
const int N=6e5;
map<int,int> M;
int cnt,a[N],cmp_d,rt;
struct re{
    int x,y,z;
}p[N];
bool cmp(re x,re y)
{
    if (!cmp_d) return x.x<y.x;
    else return x.y<y.y;
}
const int INF=1e9;
struct kd_tree{
    int v[N],pv[N],ls[N],rs[N],Mx[N],Nx[N],My[N],Ny[N];
    kd_tree()
    {
        v[0]=pv[0]=INF;
        Nx[0]=INF; Mx[0]=0;
        Ny[0]=INF; My[0]=0;
    }
    IL void updata(int x)
    {
        pv[x]=MIN(MIN(pv[ls[x]],pv[rs[x]]),v[x]);
        Mx[x]=MAX(p[x].x,MAX(Mx[ls[x]],Mx[rs[x]]));
        Nx[x]=MIN(p[x].x,MIN(Nx[ls[x]],Nx[rs[x]]));
        My[x]=MAX(p[x].y,MAX(My[ls[x]],My[rs[x]]));
        Ny[x]=MIN(p[x].y,MIN(Ny[ls[x]],Ny[rs[x]]));
    }
    int build(int h,int t,int o)
    {
        int x,mid; x=mid=(h+t)/2;
        cmp_d=o; nth_element(p+h,p+mid,p+t+1,cmp);
        v[x]=p[x].z;
        if (h<mid) ls[x]=build(h,mid-1,o^1);
        if (mid<t) rs[x]=build(mid+1,t,o^1);
        updata(x);
        return x;
    }
    int query(int x,int x1,int x2,int y1,int y2)
    {
        if (x1>Mx[x]||x2<Nx[x]||y1>My[x]||y2<Ny[x]) return(INF);
        if (x1<=Nx[x]&&Mx[x]<=x2&&y1<=Ny[x]&&My[x]<=y2) return(pv[x]);
        int ans=INF;
        if (p[x].x>=x1&&p[x].x<=x2&&p[x].y>=y1&&p[x].y<=y2) ans=v[x];
        mina(ans,query(ls[x],x1,x2,y1,y2));
        mina(ans,query(rs[x],x1,x2,y1,y2));
        return ans;
    }
}K;
int main()
{
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    int n,m;
    read(n); read(m);
    rep(i,1,n)
    {
      read(a[i]);
      int k=M[a[i]];
      if (k) p[++cnt]=(re){k,i,i-k};
      M[a[i]]=i;
    }
    rt=K.build(1,cnt,0);
    rep(i,1,m)
    {
        int x,y;
        read(x); read(y);
        int ans=K.query(rt,x,y,x,y);
        if (ans<INF) wer(ans); else wer(-1);
        wer2();
    }
    fwrite(sr,1,C+1,stdout);
    return 0;
}

原文地址:https://www.cnblogs.com/yinwuxiao/p/10100457.html

时间: 2024-10-15 23:37:35

Codeforces 522D Closest Equals的相关文章

$Codeforces\ 522D\ Closest\ Equals$ 线段树

正解:线段树 解题报告: 传送门$QwQ$ 题目大意是说给定一个数列,然后有若干次询问,每次询问一个区间内相同数字之间距离最近是多少$QwQ$.如果不存在相同数字输出-1就成$QwQ$ 考虑先预处理出每个点的$pre$和$lst$,就前一个相同数字的位置和后一个相同数字的位置$QwQ$,然后在线段树上维护下每个点到达前一个相同数字的最短距离 然后对询问按左端点排序,每次查询右端点区间内的$min$就成,然后删去数的话就把它后一个数字的那个最短距离$update$成$inf$就成鸭$QwQ$ 然后

codeforces 522D. Closest Equals 线段树+离线

题目链接 n个数m个询问, 每次询问输出给定区间中任意两个相同的数的最近距离. 先将询问读进来, 然后按r从小到大排序, 将n个数按顺序插入, 并用map统计之前是否出现过, 如果出现过, 就更新线段树. 如果当前的i等于某个询问的r, 那么就查询, 具体看代码. 1 #include <iostream> 2 #include <vector> 3 #include <cstdio> 4 #include <cstring> 5 #include <

Codeforces 962D - Merge Equals

链接: http://codeforces.com/problemset/problem/962/D 题意: 给出一个整数序列.选择其中最小且出现两次(或以上)的数,把最左边的两个从序列中移除,然后把它们的和放到它们的后面第一位.不断重复上述过程,直到序列中的每个数都是唯一的.输出最后的序列. 分析: 如果在数a的前面有一个可以跟a合并的数b,则b一定是唯一的.否则,b要先跟其他等值的数合并.这样,我们只需要从左到右依次加入每个数,不断维护当前序列的唯一性即可.方法是用map记录前面每个数值的唯

题---

把一些题放在这里----- 要补的,或者要去做的--->_< 1)  Codeforces VK Cup 2015 - Qualification Round 1 D. Closest Equals 离线线段树 求区间相同数的最小距离

CodeForces A or B Equals C

A or B Equals C Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Description standard input/outputStatements Rami went back from school and he had an easy homework about bitwise operations (and,or,..) The homework was like

Educational Codeforces Round 42 (Rated for Div. 2) D - Merge Equals

这道题我可以直接模拟 理由是一个数*2的过程中最多30次左右 2^31 = 2e9 所以我可以从小的书开始模拟这个过程 #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <map> #include <vector> #include <set> typedef long long ll; const

Educational Codeforces Round 42 D. Merge Equals (set + pll)

CF962D 题意: 给定一个数列,对于靠近左端的两个相同大小的值x可以合并成一个点.把x 乘以2 放在第二个点的位置,问最后的数列大小和每个位子的值. 思路: 利用set 配上 pair 就行了,感觉很巧妙,每次取出前两个pll  t1,t2. 如果 t1.first != t2.first ,把t2直接重新放入set中,否则,把t2.first * 2并更新t2.second 位子,把t2放入到set中.(这么说好像优先队列也可以) #include <iostream> #include

Codeforces Round #315 (Div. 1)

A. Primes or Palindromes? time limit per test 3 seconds memory limit per test 256 megabytes input standard input output standard output Rikhail Mubinchik believes that the current definition of prime numbers is obsolete as they are too complex and un

Codeforces Round #203 (Div. 2)B Resort

Resort Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 350B Description Valera's finally decided to go on holiday! He packed up and headed for a ski resort. Valera's fancied a ski trip b