首页 > 其他分享 >[IOI2015] Teams 题解

[IOI2015] Teams 题解

时间:2023-11-22 15:01:49浏览次数:33  
标签:int 题解 Top tree IOI2015 Teams read num root

妙妙题。

不难发现,我们对于每个 \(k\) 取出的人都是满足 \(a_i \leq k \leq b_i\) 的。

经典的,我们直接将 \((a_i, b_i)\) 转化到二维平面上,将它转化成一个二维数点问题。

我们对于每一个询问,都使 \(k\) 有序,从小到大贪心的选择,也就相当于 \(x\) 轴限制不断向右,\(y\) 轴限制不断向上。

如果每次的询问 \(m = 1\) 我们直接用主席树二维数点即可,但是如果 \(m > 1\),有一些点我们前面可能用掉了,后面就不能用了,所以我们考虑怎么维护用掉的点。

我们发现,在贪心的过程中,每一次我们都会选择 \(y\) 轴尽量小的点。

然后我们观察被 \(\rm ban\) 掉的点的范围,发现一定是单调递减的,如图所示,我们新 \(\rm ban\) 掉的点的顶端一定是平衡的。

理解了这些,我们再具体说说细节:

我们记一个数组 \(H\) 为我们当前栈可以被取的点中 \(y\) 最小的那一个,当我们发现 \(H < k_i\) 的时候,我们当前栈顶就失效了,很好理解。

我们再记一个数组 \(q\) 为我们当前总栈剩下多少点可以取。

以及一个数组 \(s\) 为我们当前栈所对应的 \(x\) 轴的范围 \([1, s]\)。

每一次我们通过二分获取 \(H\),如果当前 \(H\) 比栈顶的 \(H\) 还大,说明我们可以继续平摊。

code:

int n, T;
int a[L], b[L];
vector<int> e[L];
int k[L];

namespace segment_tree {
    #define mid (l + r >> 1)
    #define lson L, R, l, mid, tree[w].l
    #define rson L, R, mid + 1, r, tree[w].r
    int cnt = 0;
    const int L = 4e7 + 5;
    int root[L];
    struct node {
        int l, r, num;
    } tree[L];
    int clone(int w) {
        int nw = ++ cnt;
        tree[nw] = tree[w];
        return nw;
    }
    void pushup(int w) {
        tree[w].num = tree[tree[w].l].num + tree[tree[w].r].num;
    }
    int modify(int L, int R, int l, int r, int w, int num) {
        w = clone(w);
        if(L <= l && r <= R) { tree[w].num ++; return w; }
        if(R <= mid) tree[w].l = modify(lson, num);
        else if(mid < L) tree[w].r = modify(rson, num);
        else tree[w].l = modify(lson, num), tree[w].r = modify(rson, num);
        pushup(w);
        return w;
    }
    int query(int L, int R, int l, int r, int w) {
        if(L <= l && r <= R) return tree[w].num;
        if(R <= mid) return query(lson);
        else if(mid < L) return query(rson);
        else return query(lson) + query(rson);    
    }
    int build(int l, int r, int w) {
        if(l != r)
            tree[w].l = build(l, mid, ++ cnt), tree[w].r = build(mid + 1, r, ++ cnt), pushup(w);
        else
            tree[w].num = 0;
        return w;
    }
}

using segment_tree::build;
using segment_tree::root;
using segment_tree::modify;
using segment_tree::query;
using segment_tree::tree;

int QueryH(int L, int R, int l, int r, int num) {
    if(l == r) return l;
    if(num > tree[tree[R].r].num - tree[tree[L].r].num) return QueryH(tree[L].l, tree[R].l, l, (l + r >> 1), num - (tree[tree[R].r].num - tree[tree[L].r].num));
    else return QueryH(tree[L].r, tree[R].r, (l + r >> 1) + 1, r, num);
}

int s[L], q[L], high[L];

signed main() {
    n = read();
    rep(i, 1, n) {
        a[i] = read(), b[i] = read();
        e[a[i]].push_back(b[i]);
    }
    root[0] = build(1, n, 0);
    rep(i, 1, n) {
        root[i] = root[i - 1];
        for(auto d : e[i]) root[i] = modify(d, d, 1, n, root[i], 1);
    }
    T = read();
    while(T --) {
        int m = read();
        rep(i, 1, m) k[i] = read();
        sort(k + 1, k + 1 + m);
        int Top = 0;
        rep(i, 1, m) {
            while(high[Top] < k[i] && Top) Top --;
            int tot = query(k[i], n, 1, n, root[k[i]]) - query(k[i], n, 1, n, root[s[Top]]) + q[Top] - k[i];
            if(tot < 0) { 
                puts("0"); 
                goto leave; 
            }
            int H = QueryH(root[s[Top]], root[k[i]], 1, n, tot - q[Top]);
            while(high[Top] < H && Top) Top --, H = QueryH(root[s[Top]], root[k[i]], 1, n, tot - q[Top]);
            Top ++;
            s[Top] = k[i], q[Top] = tot, high[Top] = H;
        }
        puts("1");
        leave:;
    }
    return 0;
}

标签:int,题解,Top,tree,IOI2015,Teams,read,num,root
From: https://www.cnblogs.com/Kafuchino/p/17849026.html

相关文章

  • zookeeper3.5.5以上8080端口占用问题解决
    zookeeper3.5.5启动默认会把AdminService服务启动,这个服务默认是8080端口,是一个通过jetty启动的管理控制台,一般不会用到,网上的复制粘贴就是来自同一个办法如下:方法一、删除jetty方法二、修改端口。修改方法的方法有两种:在启动脚本中增加-Dzookeeper.admin.serverPort=你的端......
  • P9868 题解
    blog。NOIP2023T1。可以对字符串随意交换,即可以重排每个单词。对于询问\(i\),最优方案显然是将\(\forallj\nei\)的\(w_j\)重排至字典序最大,将\(w_i\)重排至字典序最小。这件事情本质是将\(w_i\)与\(\min\limits_{j\nei}w_j\)比较。在开始时将全部串重排至字典序......
  • 【AGC】鸿蒙应用软件包上传问题解析
    ​【问题背景】近期收到了一些反馈,一些鸿蒙元服务开发者在发布应用市场的过程中,上传.app包时遇到了不同的报错,导致上传失败,下面来看一下这些报错的具体原因,如何正确打包上传。 【问题描述1】HarmonyOS元服务软件包上传后,提示“软件包解析失败,请重新上传”,错误详情(5)​​​【......
  • T401305 平面划分(easy) 题解
    LinkT401305平面划分(easy)Solution平面上\(n\)条直线所划分处的区域最大个数\(L_n\)是多少我们考虑假设已经有\(n-1\)条直线,我们需要画一条直线,这条直线最多和\(n-1\)条直线相交产生\(n\)个新的区域所以我们得到了\[\begin{align*} &L_0=1\\ &L_n=L_{n-1}......
  • jsmpeg视频播放器使用方法和常见问题解决方案
    JSMpeg是一个使用JavaScript编写的视频播放器,它可以在浏览器中播放MPEG1视频和MP2音频流。JSMpeg的特点是它能够通过WebSockets实时传输视频流,并且可以在不支持HTML5视频播放器的浏览器上运行。以下是JSMpeg的基本使用方法和一些常见问题的解决方案:主要用来解决移移动端视频播放问......
  • [ABC328D] Take ABC 题解
    链接如果只是扫一遍肯定是不行的,所以我们使用一个栈,遇到C就判断栈顶的两个元素是不是分别为B和A。这样就能做出来这道题了。代码#include<bits/stdc++.h>usingnamespacestd;strings;charstk[200010];intmain(){ cin>>s; intn=s.size(),p=0;//字符串长度和......
  • 【树链剖分】P3401 洛谷树 题解
    P3401考虑先将路径权值进行转化,因为很难对路径直接进行统计。考虑如何表示出这条路径的权值。记\(s_i=\oplus_{j\in\text{path}(1,i)}w_j\),其中\(\text{path}(i,j)\)表示\(i\)到\(j\)的路径上的边集。则\(u\tov\)的路径的权值为\(s_u\opluss_v\)。现在转变为......
  • P9620 歌姬 题解
    感觉题解做法都好神秘。来一个容易理解,通俗易懂的树剖解法。思路容易发现原问题等价于维护一个虚树。每一次询问虚树的根的所有儿子的最大值。要求链修。容易发现仅仅动态维护根是好做的。我们用一个\(\text{set}\)。每次维护\(\text{dfs}\)的最小值和最大值。对于这......
  • S7-1200和KTP900basic 调试问题解决
    1:KTP900basic和S7-1200无法通讯?环境:型号:KTP900basic,订货号6AV2123-2JB03-OAX0 博图:V17原因,需要将KTP900basic更新最新的17.0面板镜像,一般需要在软件上额外安装SIMATIC_WinCC_Panel_Images_V17.ISO这个文件,下载连接:精智(Comfort)屏下载时提示缺少面板映像(siemens.com.cn......
  • error:0308010C:digital envelope routines::unsupported问题解决
    问题描述:报错:Error:error:0308010C:digitalenveloperoutines::unsupported报错原因:因为node.jsV17版本中最近发布的OpenSSL3.0,而OpenSSL3.0对允许算法和密钥大小增加了严格的限制报错详细信息:解决方案:方案1:打开IDEA终端,直接输入Linux&MacOS:exportNODE_OPTI......