Loading

accoders

 

 

A. 甲国的军队

 

 

手磨样例(误

发现需要人数为$\sum_{i=1}^n$ $a_i$$+b_x-a_x$ (最后一次少人情况下

但是不管最后一次少不少人发现按$b_i-a_i$降序排序一定最少

#include<bits/stdc++.h>
#define Re register int
#define Sa Sakura
#define _ putchar(' ')
#define el putchar('\n')
#define int long long
#define maxn 100010

using namespace std;

inline int read(){
    int x=0,f=0,c=getchar();
    while(!isdigit(c)) f|=c=='-',c=getchar();
    while(isdigit(c)) x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return f?-x:x;
} 

inline void ot(int x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) ot(x/10);putchar(x%10|48);
}

struct node{
    int a,b;
}q[maxn];

int t,n,tot,ans;

inline bool cmp(node A,node B){
    return A.b-A.a>B.b-B.a;
}

main(){
//    freopen("army2.in","r",stdin);
//    freopen("1.in","w",stdout);
    t=read();
    while(t--){
        n=read();
        tot=ans=0;
        for(Re i=1;i<=n;i++) q[i].a=read(),q[i].b=read();
        sort(q+1,q+n+1,cmp);
        for(Re i=1;i<=n;i++)
            if(tot<q[i].b){
                ans+=q[i].b-tot;
                tot=q[i].b-q[i].a;
            }else tot-=q[i].a;
        ot(ans),el;
    }
}
View Code

 

B. 虚弱

一个x对应的最大值:$\max\limits_{i=1}^{n} \text{{$s_i-i*x$}}$-$\min\limits_{j=1}^{n} \text{{$s_j-j*x$}}$ $s_i$表示前缀和

一次计算是$O(n)$的

抛开事实不谈(bushi  抛开这个式子不谈 发现x变大时虚弱程度增大 (取绝对值之前绝对值)变小时虚弱程度减小 所以最小ans对应的最小x使虚弱程度的最大最小值绝对值相等 

由于虚弱程度是对二者绝对值取max 所以这是一个单谷函数

然后我们用一个类似三分的东西解决它就行

eps设为1e-12 设为1e-9会挂

还有不要学WintersRain const int eps(话说这是第二次了吧

 

#include<bits/stdc++.h>
#define Re register int
#define Sa Sakura
#define _ putchar(' ')
#define el putchar('\n')
#define maxn 200010
#define int long long

const long double eps=1e-12;

using namespace std;

inline int read(){
    int x=0,f=0,c=getchar();
    while(!isdigit(c)) f|=c=='-',c=getchar();
    while(isdigit(c)) x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return f?-x:x;
} 

inline void ot(int x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) ot(x/10);putchar(x%10|48);
}

int n,a[maxn];
long double ans;

inline long double work(long double x){
    long double maxx=0,minn=9999999999999999;
    for(Re i=1;i<=n;i++){
        maxx=max(maxx,a[i]-i*x);
        minn=min(minn,a[i]-i*x);
    }
    return maxx-minn;
}

main(){
    n=read();
    for(Re i=1;i<=n;i++) a[i]=read()+a[i-1];
    long double l=-10000,r=10000;
    while(r-l>3*eps){
        long double mid=(l+r)/2;
    //    cout<<l<<" "<<mid<<" "<<r<<endl;
        long double midl=mid-eps,midr=mid+eps;
        long double maxmid=work(mid),maxmidl=work(midl),maxmidr=work(midr);
        if(maxmidl<maxmid&&maxmid<maxmidr) r=mid;
        else if(maxmidl>maxmid&&maxmid>maxmidr) l=mid;
        else l=midl,r=midr;
    }
    printf("%.6Lf",work(l));
}
View Code

C. 萨鲁曼的半兽人

 求的是用回文串覆盖1-n的最小数

按照题意回文串可以重叠

用前后缀哈希$O(nlogn)$或manacher$O(n)$求出

贪心 扫一段 选取最右新端点 每次进入下一段ans++

#include<bits/stdc++.h>
#define Re register int
#define Sa Sakura
#define _ putchar(' ')
#define el putchar('\n')
#define maxn 200010
#define int long long

using namespace std;

inline int read(){
    int x=0,f=0,c=getchar();
    while(!isdigit(c)) f|=c=='-',c=getchar();
    while(isdigit(c)) x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return f?-x:x;
} 

inline void ot(int x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) ot(x/10);putchar(x%10|48);
}

int d[maxn],n,ans,en[maxn];
char s1[maxn],s2[maxn];

main(){
//    freopen("orc2.in","r",stdin);
    s2[0]='|';
    while(scanf("%s",s1+1)==1){
        ans=0;
        n=strlen(s1+1);
        for(Re i=1;i<=n;i++)
            s2[(i<<1)-1]='#',s2[i<<1]=s1[i];
        s2[n<<1|1]='#';
        n=n<<1|1;
        s2[n+1]='}';
        for(Re i=1,mid=0,mr=0;i<=n;i++){
            en[i]=0;
        //    ot(i),_,ot(mid),_,ot(mr),el;
            if(i<mr){
                int j=mid*2-i;
                d[i]=min(d[j],mr-i+1);
            }else d[i]=1;
            while(s2[i+d[i]]==s2[i-d[i]]) d[i]++;
            if(i+d[i]-1>mr){
                mr=i+d[i]-1;
                mid=i;
            }
        }
    //    cout<<s2<<endl;
    //    for(Re i=1;i<=n;i++) ot(d[i]),_;el;
        for(Re i=1;i<=n;i++) en[i-d[i]+1]=i+d[i]-1;
    //    for(Re i=1;i<=n;i++) ot(en[i]),_;el;
        int p=1,r=en[1],mr=0;
    //    ot(r),el;
        while(p<n){
            p++;
            if(p>r) ans++,r=mr;//,ot(mr),el;
            mr=max(mr,en[p+1]);
        }
        ot(ans),el;
    }
}
View Code

D. 序列

 

贪心 先选取一个最小值再在其后选取次小值

但是为了其能最后被选到 剩下的三个区间长度必须是偶数

so最小值的必须是区间的奇数位(不是下标的奇数位)次小值相反

维护奇数偶数两张ST表 奇数位的数在偶数表里值设为正无穷

可以递归(建三叉树)或线性处理

最后发现如果两个对无辈分关系则无先后关系 与深度无关

将根塞入优先队列 每次选一个最小对pop并输出 并向优先队列中加入他的儿子

就保证了先后关系

递归代码丢了 下面是线性代码

#include<bits/stdc++.h>
#define Re register int
#define Sa Sakura
#define _ putchar(' ')
#define el putchar('\n')
#define maxn 200010

using namespace std;

inline int read(){
    int x=0,f=0,c=getchar();
    while(!isdigit(c)) f|=c=='-',c=getchar();
    while(isdigit(c)) x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return f?-x:x;
} 

inline void ot(int x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) ot(x/10);putchar(x%10|48);
}

struct node{
    int x,y,id;
}q[maxn];

inline bool operator<(node A,node B){
    return A.x>B.x;
}

vector<int> G[maxn];
priority_queue<node> que;
int n,a[maxn],min1[maxn][20],min2[maxn][20];
int tot,cnt,pos1[maxn],pos2[maxn],num,fa[maxn];
int L[maxn],R[maxn];
bool vis[maxn];

inline int getmin1(int l,int r){
    if(l==r) return l;
    int k=log2(r-l+1);
//    _,ot(l),_,ot(r),_,ot(k),el;
    return a[min1[l][k]]<a[min1[r-(1<<k)+1][k]]?min1[l][k]:min1[r-(1<<k)+1][k];
}

inline int getmin2(int l,int r){
    if(l==r) return l;
    int k=log2(r-l+1);
//    _,ot(l),_,ot(r),_,ot(k),el;
    return a[min2[l][k]]<a[min2[r-(1<<k)+1][k]]?min2[l][k]:min2[r-(1<<k)+1][k];
}


inline void solve(int l,int r){
//    _,ot(r),_,ot(l),el;el;
    pos1[tot]=l&1?getmin1(l,r):getmin2(l,r);
    pos2[tot]=l&1?getmin2(pos1[tot]+1,r):getmin1(pos1[tot]+1,r);
    q[tot]=node{a[pos1[tot]],a[pos2[tot]],tot};
//    ot(pos1[tot]),_,ot(pos2[tot]),el;
//    ot(tot),_,ot(q[tot].x),_,ot(q[tot].y),el;el;
    int cn=num;
    if(pos1[tot]!=l) L[++num]=l,R[num]=pos1[tot]-1;
    if(pos2[tot]!=pos1[tot]+1) L[++num]=pos1[tot]+1,R[num]=pos2[tot]-1;
    if(pos2[tot]!=r) L[++num]=pos2[tot]+1,R[num]=r; 
    if(cn!=num) fa[cn+1]=tot;
}

bool spj(){
    for(Re i=1;i<=n;i++) if(a[i]!=i) return false;
    for(Re i=1;i<=n;i++) ot(a[i]),_;
    return true;
}

main(){
//    freopen("seq2.in","r",stdin);
//    freopen("1.in","r",stdin);
    n=read();
    a[n+1]=99999999;
    for(Re i=1;i<=n;i++){
        a[i]=read();
        if(i&1) min1[i][0]=i,min2[i][0]=n+1;
        else min1[i][0]=n+1,min2[i][0]=i;
    }
//    if(spj()){
//        return 0;
//    }
    for(Re j=1;j<=17;j++)
        for(Re i=1;i+(1<<j)-1<=n;i++){
            min1[i][j]=a[min1[i][j-1]]<a[min1[i+(1<<j-1)][j-1]]?min1[i][j-1]:min1[i+(1<<j-1)][j-1];
            min2[i][j]=a[min2[i][j-1]]<a[min2[i+(1<<j-1)][j-1]]?min2[i][j-1]:min2[i+(1<<j-1)][j-1];
        }
//    for(Re i=1;i<=n/2;i++){
//        for(Re j=0;j<=1;j++) ot(min1[i][j]),_;el;
//    }    
//    for(Re i=1;i<=n/2;i++){
//        for(Re j=0;j<=1;j++) ot(min2[i][j]),_;el;
//    }
    L[1]=1,R[1]=n;
    num=1;
    while(tot<num){
        tot++;
        if(!fa[tot]) fa[tot]=fa[tot-1];
        G[fa[tot]].push_back(tot);
        solve(L[tot],R[tot]);
    }
    que.push(q[1]);
    while(!que.empty()){
        int x=que.top().id;
        que.pop();
        ot(q[x].x),_,ot(q[x].y),_;
        int p=1;
        for(Re i=0;i<G[x].size();i++) que.push(q[G[x][i]]);
    }
}
View Code

 

posted @ 2022-07-23 11:14  hzoi_Sakura  阅读(304)  评论(15编辑  收藏  举报