第十四次考试

鬼知道\(cjx\)从哪里扣的题目(特别是T2),感觉全是坑,T1卡精度,T2写压位高精才满分,T3机房的\(dalao\)们有\(inf\)种解法。。

T1 拖拉机

【题目描述】:
啦啦啦,宇宙级帅锅\(TYH\)(没错就是陶一刀)又开着他心爱的拖拉机上学去了,由于他魅力四射,一路上遇到很多妹子,这些妹子都非要跟着他,他也只好勉为其难。一开始\(TYH\)的拖拉机速度为\(1km/min\),但妹子的体重实在不忍直视,以至于当他带上\(i\)个妹子以后,他的速度会降到\(\frac{1}{(i + 1)}km/min\),例如当他带上\(1\)个妹子时,速度为\(\frac{1}{2}\)\(2\)个妹子时,速度为\(\frac{1}{3}\),以此类推。
\(TYH\)\(RP\)是如此的好,上天总是在他到达整数距离或整数时刻的时候让一个妹子出现。\(TYH\)想知道他多久才能到学校。
【输入格式】:
第一行两个正整数\(n\),\(m\),表示妹子的数量和\(TYH\)距离学校的距离。
接下来\(n + 1\)行,每行有两种形式:

  1. \(Dist\) \(x\) 表示在距离到达 \(x\) \(km\)时出现一个妹子
  2. \(Time\) \(x\) 表示在时间到达 \(x\) \(min\)的时候出现一个妹子

【输出格式】:
一行一个数,表示\(TYH\)到达学校的时间,如果不能整除,直接输出整数部分。
【样例输入】:

2 20
Time 3
Dist 10

【样例输出】:

47

【数据范围】:
对于\(30\)%数据,\(1\) <= \(n\),\(m\) <= \(50\)
对于\(50\)%数据,\(1\) <= \(n\),\(m\) <= \(2000\)
对于\(100\)%数据,\(1\) <= \(n\),\(m\) <= \(200000\),\(0\) <= \(x\) <= \(1e9\)

思路:

直接模拟即可,判断属性分别为\(Time\)\(Dist\)的妹子被遇到的先后顺序,然后直接\(pick\) \(up\)就可以了。注意判断哪些在学校之后的妹子,直接甩了不要。。反正陶一刀女朋友够

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;

char s[5];

const int MAXN = 200005;

double ti[MAXN],di[MAXN];

int main(){
    int n;double m;scanf("%d%lf",&n,&m);
    int t=0,d=0;
    for(int i=1;i<=n;++i){
        scanf("%s",s);
        if(s[0] == 'T'){
            double a;scanf("%lf",&a);
            ti[++t] = a;
        }
        else{
            double a;scanf("%lf",&a);
            if(a >= m) continue;
            di[++d] = a;
        }
    }
    sort(ti+1,ti+1+t);
    sort(di+1,di+1+d);
    if(ti[1] >= m){
        printf("%.0lf",m);
        return 0;
    }
    int h1=1;int h2=1;double ans = 1.0;
    double cost = 0.0;double DIS = 0.0;
    while(h1!=t+1 || h2!=d+1){1. 
        double v = 1/ans*1.0;
        if(DIS >= m) break;
        if((ti[h1] - cost < (di[h2]-DIS)/v && h1!=t+1) || h2 == d+1){
            DIS += (ti[h1]-cost)*v;
            cost = ti[h1];
            h1++;
            ans+=1.0;
            continue;
        }
        if((ti[h1] - cost > (di[h2]-DIS)/v && h2!=d+1) || h1 == t+1){
            cost += (di[h2]-DIS)/v;
            DIS = di[h2];
            h2++;
            ans+=1.0;
            continue;
        }
        if(ti[h1] - cost == (di[h2]-DIS)/v - cost && h2!=d+1 && h1!=t+1){
            cost = ti[h1];
            DIS = di[h2];
            h1++;h2++;ans+=2.0;
            continue;
        }
    }
    double v = 1/ans*1.0;
    cost += (m - DIS)/v;
    printf("%.0lf",floor(cost));
    return 0;
}

T2 序列操作

【题面描述】:
\(CJJ\)\(SCOI2012\)那道序列操作做吐了,于是他想出了一道简单的序列操作的题目自我安慰。
有一个包含\(n\)个数序列的\(A_i\),她想找出两个非空的集合\(S\)\(T\)
这两个集合要满足以下的条件:

  1. 两个集合中的元素都为整数,且都在\([1,n]\) 里,即\(S_i\)\(T_i\)\([1,n]\)
  2. 对于集合\(S\)中任意一个元素\(x\),集合\(T\)中任意一个元素\(y\),满足\(x < y\)
  3. 对于大小分别为p, q的集合S与T,满足:
    \(A[s_1]\) \(xor\) \(A[s_2]\) \(xor\) \(A[s_3]\) ... \(xor\) \(A[s_p]\) =
    \(A[t_1]\) \(and\) \(A[t_2]\) \(and\) \(A[t_3]\) ... \(and\) \(A[t_q]\)

上式中的\(xor\)\(and\)分别表示位运算异或运算和与运算。
\(CJJ\)想知道一共有多少对这样的集合\((S,T)\),既然你都来了,就帮忙一起算一下吧。
【输入格式】:
第一行,一个整数\(n\)
第二行,\(n\)个整数,代表\(A_i\)
【输出格式】:
仅一行,表示最后的答案。
【样例输入】:

4   
1 2 3 3  

【样例输出】:

4  

【数据范围】:
对于\(30\)%的数据, \(1 <= n <= 10\)
对于\(70\)%的数据, \(1 <= n <= 100\)
对于\(100\)%的数据,\(1 <= n <= 1000, 0 <= ai < 1024\)

思路:

这TM明明比序列操作还难好吗。表示当时题都没看懂:)
\(Dp\),两个数相等就相当于两个数的\(xor\)\(0\)。设 \(f[i][j][k=0..2]\)代表 处理到第 \(i\) 个数,如果 \(k = 1\)代表\(and\)值为\(j\),如果\(k = 2\)代表\(xor\) 值为 \(j\),如果\(k = 0\)则代表一个元素都没取。所以很容易得到方程:

  • \(f[i][j][0] = f[i + 1][j][0]\)
  • \(f[i]\)[\(j\) & \(a_i\)]\([1]\) = \(f[i + 1][j][1] + f[i + 1][j][0] + f[i + 1][j\) & \(a_i\)]\([1]\)
  • \(f[i][j\) ^ \(a_i2]\) = \(f[i + 1][j][1] + f[i + 1][j][2] + f[i + 1][j\) ^ \(a_i][2]\);

最后\(f[1][0][2]\)就是答案, 复杂度为\(O(n * 1024 * 3)\)
\(DP\)还可以分开用\(f[i][j]\)\(g[i][j]\)表示前\(i\)\(xor\)值为\(j\),后\(i\)\(and\)值为\(j\)的方案数, 随后枚举分界点\(k\)来求总方案数。复杂度\(O(n * 1024 * 3)\)
但是。。。。。。

没错你没有看错,没加高精度只有70dpts!!!

于是这道题还要愉快地加上高精度。。。
本人高精度写得丑,用了一下\(jacktang\)

#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#define LL long long
#define gch getchar
#define pch putchar
using namespace std;
template <class X> inline void read(X &x){
    x=0;char ch=gch();X f=1;
    while(ch>'9' || ch<'0') {if(ch=='-') f=-1;ch=gch();}
    while(ch>='0' && ch<='9') {x=(x<<1)+(x<<3)+ch-48;ch=gch();}
    x*=f;
}
const int MAXN=1000+5;
LL n,a[MAXN];

struct huge{
    #define N_huge 110
    #define base 100000000
    static char s[N_huge*10];
    typedef long long value;
    value a[N_huge];int len;
    void clear(){len=1;a[len]=0;}
    huge(){clear();}
    huge(value x){*this=x;}
    huge(char s[]){this->str(s);}
    huge operator =(const huge &b){
        len=b.len;for (int i=1;i<=len;++i)a[i]=b.a[i]; return *this;
    }
    huge operator +(const huge &b){
        int L=len>b.len?len:b.len;huge tmp;
        for (int i=1;i<=L+1;++i)tmp.a[i]=0;
        for (int i=1;i<=L;++i){
            if (i>len)tmp.a[i]+=b.a[i];
            else if (i>b.len)tmp.a[i]+=a[i];
            else {
                tmp.a[i]+=a[i]+b.a[i];
                if (tmp.a[i]>=base){
                    tmp.a[i]-=base;++tmp.a[i+1];
                }
            }
        }
        if (tmp.a[L+1])tmp.len=L+1;
            else tmp.len=L;
        return tmp;
    }
    huge operator -(huge b){
        int L=len>b.len?len:b.len;huge tmp;
        for (int i=1;i<=L+1;++i)tmp.a[i]=0;
        for (int i=1;i<=L;++i){
            if (i>b.len)b.a[i]=0;
            tmp.a[i]+=a[i]-b.a[i];
            if (tmp.a[i]<0){
                tmp.a[i]+=base;--tmp.a[i+1];
            }
        }
        while (L>1&&!tmp.a[L])--L;
        tmp.len=L;
        return tmp;
    }
    huge operator *(const huge &b)const{
        int L=len+b.len;huge tmp;
        for (int i=1;i<=L;++i)tmp.a[i]=0;
        for (int i=1;i<=len;++i)
            for (int j=1;j<=b.len;++j){
                tmp.a[i+j-1]+=a[i]*b.a[j];
                if (tmp.a[i+j-1]>=base){
                    tmp.a[i+j]+=tmp.a[i+j-1]/base;
                    tmp.a[i+j-1]%=base;
                }
            }
        tmp.len=len+b.len;
        while (tmp.len>1&&!tmp.a[tmp.len])--tmp.len;
        return tmp;
    }
    /*huge operator *(const huge &b){
        int L=len+b.len;huge tmp;
        for (int i=1;i<=L;++i)tmp.a[i]=0;
        for (int i=1;i<=len;++i)
            for (int j=1;j<=b.len;++j)
                tmp.a[i+j-1]+=a[i]*b.a[j];
        tmp.len=len+b.len;
        for (int i=1;i<tmp.len;++i)
            if (tmp.a[i]>=base){
                tmp.a[i+1]+=tmp.a[i]/base;
                tmp.a[i]%=base;
            }
        while (tmp.len>1&&!tmp.a[tmp.len])--tmp.len;
        return tmp;
    }*/
    pair<huge,huge> divide(const huge &a,const huge &b){
        int L=a.len;huge c,d;
        for (int i=L;i;--i){
            c.a[i]=0;d=d*base;d.a[1]=a.a[i];
            //while (d>=b){d-=b;++c.a[i];}
            int l=0,r=base-1,mid;
            while (l<r){
                mid=(l+r+1)>>1;
                if (b*mid<=d)l=mid;
                    else r=mid-1;
            }
            c.a[i]=l;d-=b*l;
        }
        while (L>1&&!c.a[L])--L;c.len=L;
        return make_pair(c,d);
    }
    huge operator /(value x){
        value d=0;huge tmp;
        for (int i=len;i;--i){
            d=d*base+a[i];
            tmp.a[i]=d/x;d%=x;
        }
        tmp.len=len;
        while (tmp.len>1&&!tmp.a[tmp.len])--tmp.len;
        return tmp;
    }
    value operator %(value x){
        value d=0;
        for (int i=len;i;--i)d=(d*base+a[i])%x;
        return d;
    }
    huge operator /(const huge &b){return divide(*this,b).first;}
    huge operator %(const huge &b){return divide(*this,b).second;}
    huge &operator +=(const huge &b){*this=*this+b;return *this;}
    huge &operator -=(const huge &b){*this=*this-b;return *this;}
    huge &operator *=(const huge &b){*this=*this*b;return *this;}
    huge operator /=(const huge &b){*this=*this/b;return *this;}
    huge operator %=(const huge &b){*this=*this%b;return *this;}
    huge &operator ++(){huge T;T=1;*this=*this+T;return *this;}
    huge &operator --(){huge T;T=1;*this=*this-T;return *this;}
    huge operator ++(int){huge T,tmp=*this;T=1;*this=*this+T;return tmp;}
    huge operator --(int){huge T,tmp=*this;T=1;*this=*this-T;return tmp;}
    huge operator +(value x){huge T;T=x;return *this+T;}
    huge operator -(value x){huge T;T=x;return *this-T;}
    huge operator *(value x){huge T;T=x;return *this*T;}
    //huge operator /(value x){huge T;T=x;return *this/T;}
    //huge operator %(value x){huge T;T=x;return *this%T;}
    huge operator *=(value x){*this=*this*x;return *this;}
    huge operator +=(value x){*this=*this+x;return *this;}
    huge operator -=(value x){*this=*this-x;return *this;}
    huge operator /=(value x){*this=*this/x;return *this;}
    huge operator %=(value x){*this=*this%x;return *this;}
    bool operator ==(value x){huge T;T=x;return *this==T;}
    bool operator !=(value x){huge T;T=x;return *this!=T;}
    bool operator <=(value x){huge T;T=x;return *this<=T;}
    bool operator >=(value x){huge T;T=x;return *this>=T;}
    bool operator <(value x){huge T;T=x;return *this<T;}
    bool operator >(value x){huge T;T=x;return *this>T;}
    huge operator =(value x){
        len=0;
        while (x)a[++len]=x%base,x/=base;
        if (!len)a[++len]=0;
        return *this;
    }
    bool operator <(const huge &b){
        if (len<b.len)return 1;
        if (len>b.len)return 0;
        for (int i=len;i;--i){
            if (a[i]<b.a[i])return 1;
            if (a[i]>b.a[i])return 0;
        }
        return 0;
    }
    bool operator ==(const huge &b){
        if (len!=b.len)return 0;
        for (int i=len;i;--i)
            if (a[i]!=b.a[i])return 0;
        return 1;
    }
    bool operator !=(const huge &b){return !(*this==b);}
    bool operator >(const huge &b){return !(*this<b||*this==b);}
    bool operator <=(const huge &b){return (*this<b)||(*this==b);}
    bool operator >=(const huge &b){return (*this>b)||(*this==b);}
    void str(char s[]){
        int l=strlen(s);value x=0,y=1;len=0;
        for (int i=l-1;i>=0;--i){
            x=x+(s[i]-'0')*y;y*=10;
            if (y==base)a[++len]=x,x=0,y=1;
        }
        if (!len||x)a[++len]=x;
    }
    void read(){
        scanf("%s",s);this->str(s);
    }
    void print(){
        printf("%d",(int)a[len]);
        for (int i=len-1;i;--i){
            for (int j=base/10;j>=10;j/=10){
                if (a[i]<j)printf("0");
                    else break;
            }
            printf("%d",(int)a[i]);
        }
    }
};char huge::s[N_huge*10];

huge f[2][1025][2];
int cur;

int main(){
    read(n);
    for(int i=1;i<=n;++i) read(a[i]);
    cur=0;
    f[cur][a[n]][0]=1;
    for(int i=n-1;i>=1;--i){
        cur^=1;
        for(int j=0;j<1024;++j) f[cur][j][0]=f[cur][j][1]=0;
        f[cur][a[i]][0]=1;
        for(int j=0;j<1024;++j){
            f[cur][j][0]+=f[cur^1][j][0];
            f[cur][j][1]+=f[cur^1][j][1];
            f[cur][j & a[i]][0]+=f[cur^1][j][0];
            f[cur][j ^ a[i]][1]+=f[cur^1][j][0]+f[cur^1][j][1];
        }
    }
    f[cur][0][1].print();
    return 0;
}

T3 天神下凡

不知道为神马取个这么高端的名字,就是\(vijos\)上的原题。。
月光的魔法
题面就不赘述了,我在\(vijos\)上也发了题解的,搬运过来算了。。

思路:

考虑一种新方法:括号匹配。
对于每一个圆,记录其左右分别能到达的最远点\(l\) , \(r\)
显然 \(l\) = \(O\)(圆心) - \(R\)(半径); \(r = O + R\)。分别为左括弧和右括弧
然后得到一个\(2n\)的数组。
对于任意一个圆,其贡献仅有可能为两种:\(1\)\(2\),其中\(1\)不必解释,当一个圆被其他圆沿半径方向分为两半,其贡献则为\(2\)
则考虑括弧匹配,对于任意一个左括弧,记录其贡献值\(add\)。有以下情况:

  1. 对于连续两个 \((\) ,他们的坐标相同,则前面一个的贡献暂时为\(1\)
  2. 对于 \()\) 的出现,在栈中弹出第一个元素并把他的贡献\(+1\)记录到答案
  3. 对于连续的两个 \()\) 的出现,且坐标相同,则栈顶的 \((\) 贡献暂时为\(1\)
  4. 对于连续的 \()\)\((\) 出现,若坐标相同,则栈顶的 \((\) 贡献暂时为\(1\)

非以上情况所述,\(add\)均为\(0\)
最后答案\(+1\),表示最外面的区域。复杂度\(O(nlogn + 2n)\)

#include<cstdio>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;
int n;
const int MAXN = 300005;
struct point{
    int l,r,val,add;
}p[MAXN<<1];point s[MAXN<<1];point p1,p2;

inline bool cmp(const point a,const point b){
    if(a.val == b.val) return a.r > b.r;
    else return a.val < b.val;
}

inline void read(int&x){
    x = 0;
    bool flag = false;
    char c = getchar();
    while (c<'0'||c>'9'){ 
        if (c == '-')
            flag = true; 
        c = getchar();
    } 
    while (c>='0'&&c<='9'){
        x = x*10+c-'0';
        c = getchar();
    }
    if (flag)
        x = -x;
}

int main(){
    read(n);int u = 0;
    for(int i=1;i<=n;++i){
        int o,r;read(o);read(r);
        p1.val = o + r;p2.val = o - r;
        p1.r = 1;p1.l = 0;p2.r = 0;p2.l = 1;
        p1.add = p2.add = 0;
        p[++u] = p1;
        p[++u] = p2;
    }
    sort(p+1,p+1+u,cmp);int tot=0;
    s[++tot] = p[1];int ans = 0;
    int last = inf;
    for(int i=2;i<=u;++i){
        if(p[i].l){
            if(p[i].val == s[tot].val) s[tot].add = 1;
            if(last != inf){
                if(p[i].val != last) s[tot].add = 0;
            }
            last = inf;
            s[++tot] = p[i];
        }
        if(p[i].r){
            if(last == inf) last = p[i].val;
            else{
                if(p[i].val !=  last) s[tot].add = 0;
                last = p[i].val;
            }
            ans += (1 + s[tot].add);
            tot--;
        }
    }
    printf("%d",ans+1);
    return 0;
}

然而>_>
机房\(dalao\)多,做法千万种,种种踩\(std\)

比如:(蜜汁二分\(rank1\)

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define inl inline
#define ll long long
template<class X>inl void read(X &x)
{
    X f=1;x=0;char c=getchar();
    for(;c>'9'||c<'0';c=getchar())if(c=='-')f=-1;
    for(;c<='9'&&c>='0';c=getchar())x=x*10+c-'0';
    x=x*f;
}
#define inf 1061109567
#define N 300005
#define rgs register 
struct cer{int l,r;}c[N];
inl bool cmp(const cer &a,const cer &b){return (a.l^b.l)?(a.l<b.l):(a.r>b.r);}
int n;
int r[N];//r:(最大的)右边缘外切圆; 
int findr(int x)
{
    int L=x+1,R=n,goal=c[x].r,ans=0;
    while(L<=R)
    {
        int mid(L+R>>1);
        if(c[mid].l==goal)ans=mid;
        if(c[mid].l>=goal)R=mid-1;
        else L=mid+1;
    }
    if(ans)while(c[ans-1].l==c[ans].l)--ans;
    r[x]=ans;
    return ans;
}
int main()
{
    memset(r,-1,sizeof r);
    read(n);
    for(rgs int i=1;i<=n;++i)
    {
        int x,r;
        read(x),read(r);
        c[i].l=x-r,c[i].r=x+r;
    }sort(c+1,c+1+n,cmp);
    rgs int ans=1;
    for(rgs int i=1;i<=n;++i)
    {
        int x=i,Re=c[i].r;
        if(c[x+1].l^c[x].l){++ans;continue;}
        ++x;
        while(x)
        {
            x=(~r[x])?r[x]:findr(x);
            if(c[x].r==Re){++ans;break;}
        }++ans;
    }
    printf("%d",ans);
    return 0;
}

或者:线段树+离散化(\(4000ms+\)

#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#define LL long long
#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define gch getchar
#define pch putchar
#define ls (now<<1)
#define rs (now<<1|1)
using namespace std;
template <class X> inline void read(X &x){
    x=0;char ch=gch();X f=1;
    while(ch>'9' || ch<'0') {if(ch=='-') f=-1;ch=gch();}
    while(ch>='0' && ch<='9') {x=(x<<1)+(x<<3)+ch-48;ch=gch();}
    x*=f;
}
template <class X> inline void print(X x){
    if(x<0) pch('-'),x=-x;
    if(x>9) print(x/10);
    pch(x%10+48);
}

const int MAXN=300000+5;

int n,hash[MAXN<<1],hash_cnt,cnt;

struct Segment{
    int l,r,len;
    bool operator < (const Segment &x)const{
        return len<x.len;
    }
}s[MAXN];

inline int pos(int x){
    return lower_bound(hash+1,hash+1+hash_cnt,x)-hash;
}

struct Segment_tree{
    int cou[MAXN<<3];
    inline void cover(int now,int l,int r,int L,int R){
        if(L<=l && r<=R){cou[now]++;return;}
        int mid=(l+r)>>1;
        if(L<=mid) cover(ls,l,mid,L,R);
        if(R>mid) cover(rs,mid+1,r,L,R);
        cou[now]=min(cou[ls],cou[rs]);
    }
    inline bool check(int now,int l,int r,int L,int R){
        if(L<=l && r<=R) return cou[now];
        int mid=(l+r)>>1;
        if(L<=mid && R>mid) return check(ls,l,mid,L,R)&&check(rs,mid+1,r,L,R);
        else if(L<=mid) return check(ls,l,mid,L,R);
        else if(R>mid) return check(rs,mid+1,r,L,R);
    }
}T;

int main(){
    read(n);
    for(int i=1;i<=n;++i){
        int x,y;read(x);read(y);
        s[i].l=x-y;s[i].r=x+y-1;
        s[i].len=y<<1;
        hash[++cnt]=s[i].l;
        hash[++cnt]=s[i].r;
    }
    sort(hash+1,hash+1+cnt);
    hash_cnt=unique(hash+1,hash+1+cnt)-(hash+1);
    for(int i=1;i<=n;++i){
        s[i].l=pos(s[i].l);
        s[i].r=pos(s[i].r);
    }
    sort(s+1,s+1+n);
    int ans=n+1;
    for(int i=1;i<=n;++i){
        if(T.check(1,1,hash_cnt,s[i].l,s[i].r)) ans++;
        T.cover(1,1,hash_cnt,s[i].l,s[i].r);
    }
    print(ans);
    return 0;
}

\(or\) 并查集大法好

#include<map>
#include<cstdio>
#include<iostream>
#include<algorithm>
#define N 300005
using namespace std;

inline int read(){
    int e=0,ch=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')ch=-1;c=getchar();}
    while(c>='0'&&c<='9'){e=e*10+(c-48);c=getchar();}
    return e*ch;
}

int n,ans,m,c,d,cnt;
int b[N<<1],fa[N<<1];

struct node{
    int l,r;
}e[N];

struct ndqe{
    int rank,w,id,to;
}pp[N<<1];

inline int fin(int x){
    if(fa[x]!=x) return fa[x]=fin(fa[x]);
    return x;
}

inline bool cmp(ndqe x,ndqe y){
    return x.w<y.w;
}

inline bool cmp2(node x,node y){
    return (x.r-x.l)<(y.r-y.l);
}

int main(){
    n=read();
    ans=n+1;
    for(int i=1;i<=n;++i){
        c=read();
        d=read();
        e[i].l=c-d;
        e[i].r=c+d;
        pp[++cnt].id=i;
        pp[cnt].w=c-d;
        pp[cnt].to=1;
        pp[++cnt].id=i;
        pp[cnt].w=c+d;
        pp[cnt].to=0;
    }
    sort(pp+1,pp+cnt+1,cmp);
    pp[1].rank=1;
    for(int i=2;i<=cnt;++i){
        if(pp[i].w>pp[i-1].w) pp[i].rank=pp[i-1].rank+1;
        else pp[i].rank=pp[i-1].rank;
    }
    for(int i=1;i<=cnt;++i){
        if(pp[i].to) e[pp[i].id].l=pp[i].rank;
        else e[pp[i].id].r=pp[i].rank;
    }
    for(int i=1;i<=pp[cnt].rank;++i) fa[i]=i;
    sort(e+1,e+n+1,cmp2);
    for(int i=1;i<=n;++i){
        int l=e[i].l,r=e[i].r;
        l=fin(l),r=fin(r);
        if(l==r) ans++;
        else fa[l]=r;
    }
    printf("%d",ans);
    return 0;
}

还有一个奇怪的栈模拟

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std;
struct Info {
    int left,r,o,right,ind;
    
    Info(int o,int r) {
        this->left = o - r;
        this->right = o + r;
        this->r = r;
        this->o = o;
    }
    Info(Info info,int ind) {
        this->ind = ind;
        this->left = info.left;
        this->right = info.right;
        this->r = info.r;
        this->o = info.o;
    }
    Info(){
    }
    
    bool operator<(Info info) const {
        if (left == info.left)
            return r>info.r;
        else return left<info.left;
    }
};

Info infos[300005];

stack<Info> sta;

int sizes[300005];

void read(int&x){cin>>x;}

int main() {
    int n;
    read(n);
    for (int i = 0;i<n;i++) {
        int o,r;
        read(o);
        read(r);
        infos[i] = Info(o,r);
    }
    sort(infos,infos+n);
    int ans = 2;
    sta.push(Info(infos[0],0));
    for (int i = 1;i<n;i++) {
        ans++;
        Info info = infos[i];
        Info top = sta.top();
        while (info.left>=top.right&&!sta.empty()) {
            sta.pop();
            if (!sta.empty())
                top = sta.top();
        }
        if (!sta.empty())  
            sizes[top.ind] += info.r*2;
        sta.push(Info(info,i));
    }
    for (int i = 0;i<n;i++) 
        if (sizes[i]==infos[i].r*2) 
             ans++;
    cout<<ans<<endl;
} 

猜你喜欢

转载自www.cnblogs.com/lajioj/p/9466233.html