• E. XKC's basketball team

求比w[i]大m的最远位置。
比赛的时候一直在看B题浪费了很多时间。。(思路也不对。)
维护一个后缀最大值,查找时二分查找后缀最大值大于等于w[i]+m的最右端


#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e6+10;
#define INF  0x3f3f3f3f
#define s1(a) scanf("%d",&a)
#define s2(a,b) scanf("%d %d",&a,&b)
int n,m;
int w[MAXN];
int ww[MAXN];
int main()
{
    s2(n,m);ww[n]=0;
    for(int i=0;i<n;i++) s1(w[i]);
    for(int i=n-1;i>=0;i--) ww[i]=max(w[i],ww[i+1]);
    for(int i=0;i<n;i++)
    {
        int x=w[i]+m,l=i,r=n;
        if(ww[i]<x) 
        {
            printf("-1%c",i==n-1?'\n':' ');
            continue;
        }
        while(l<r)
        {
            int mid=(l+r)>>1;
            if(ww[mid]>=x)
                l=mid+1;
            else 
                r=mid;
        }
        printf("%d%c",l-i-2,i==n-1?'\n':' ');
    }
}
  • B. so easy

给出q次操作,删除某值或者询问某值之后未被删除的第一个值;
n1e9,q1e6
比赛的时候拿分块写当然T掉了,n范围太大了摔。要学会灵活使用STL啊。。
逆向思维还是很重要的,对于每个删除操作存储该值,有两种方法,
一种直接拿set,查找时暴力查找(count函数)
一种用map加并查集的方法,对于每个删除操作更新该点的父亲节点,使每个节点指向他右侧第一个有效点
#include<bits/stdc++.h>
using namespace std;
unordered_map<int,int> mp;
int n,m;
int find_pre(int x){
    if(!mp.count(x)) return x;
    return mp[x]=find_pre(mp[x]);
}
int main(){
    scanf("%d %d",&n,&m);
    int op,x;
    while(m--){
        scanf("%d %d",&op,&x);
        if(op==1)
            mp[x]=find_pre(x+1);
        else{
            x=find_pre(x);
            if(x>n) printf("-1\n");
            else printf("%d\n",x);
        }
    }
    return 0;
}
#第一次知道unordered_map,涨知识了/
map和set差不多都有内置红黑树,就会自动按key值按字典序从小到大排序
 而unordered_map 是采用了哈希函数,没有了排序功能 从名字就看的出来。。。 
但是我们甚至可以用常数的时间进行查找的功能 最坏情况下也才是O(n) 而map的话因为排序了起步都是O(nlogn)