zoukankan      html  css  js  c++  java
  • contest-20191021

    文化课读的真开心

    回来竞赛

     

    假人

    sol

    根据不等式有 abs(a-b)+abs(b-c)>=abs(a-c)

    那么每一个都会选。

    可以发现每一段只会选在端点上(否则移到端点更优)。

    那么dp f[i][0/1]表示前i个选在上/下端点的最大值。

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define maxn 100005
    using namespace std;
    int n,a[maxn][2];
    long long s1,s2,f[maxn][2];
    int main()
    {
        freopen("arachne.in","r",stdin);
        freopen("arachne.out","w",stdout);
        cin>>n;
        for(int i=1;i<=n;i++)scanf("%d%d",&a[i][0],&a[i][1]);
        for(int i=2;i<=n;i++){
            s1=max(abs(a[i][0]-a[i-1][1])+f[i-1][1],abs(a[i][0]-a[i-1][0])+f[i-1][0]);
            s2=max(abs(a[i][1]-a[i-1][1])+f[i-1][1],abs(a[i][1]-a[i-1][0])+f[i-1][0]);
            f[i][0]=s1;f[i][1]=s2;
        }
        cout<<max(f[n][0],f[n][1])<<endl;
        return 0;
    }
    View Code

    愚者

    sol

    考虑把点按权值大到小加入,用并查集维护联通快大小,那么每次加入的一定是最小值。
    把式子展开,发现它形如y=kx+b.

    每次得到一组(k,b)

    对这些直线构出下凸壳,线性处理ans

    100%数据范围小于部分分范围是什么鬼,差评投诉

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define maxn 300005
    #define ll long long
    using namespace std;
    int n,m,Q,head[maxn],tot;
    int f[maxn],sz[maxn],flag[maxn];
    ll ans[maxn];
    struct line{
        ll a,b;
    }s[maxn],li[maxn],l[maxn],q[maxn];
    struct node{
        int v,nex;
    }e[maxn];
    void add(int t1,int t2){
        e[++tot].v=t2;e[tot].nex=head[t1];head[t1]=tot;
    }
    bool cmp(line A,line B){return A.a>B.a;}
    bool dmp(line A,line B){return A.a<B.a||(A.a==B.a&&A.b<B.b);}
    int getf(int k){return f[k]==k?k:f[k]=getf(f[k]);}
    double C(line A,line B){
        return (double)(B.b-A.b)/(double)(A.a-B.a);
    }
    int main()
    {
        cin>>n>>m>>Q;
        for(int i=1;i<=n;i++){
            scanf("%lld",&s[i].a),s[i].b=i;
            f[i]=i;sz[i]=1;
        }
        for(int i=1,t1,t2;i<=m;i++){
            scanf("%d%d",&t1,&t2);
            add(t1,t2);add(t2,t1);
        }
        for(int i=1;i<=Q;i++)scanf("%lld",&q[i].a),q[i].b=i;
        sort(s+1,s+n+1,cmp);
        for(int x=1;x<=n;x++){
            flag[s[x].b]=1;
            for(int i=head[s[x].b];i;i=e[i].nex){
                if(flag[e[i].v]){
                    int fv=getf(e[i].v);
                    if(fv!=s[x].b)f[fv]=s[x].b,sz[s[x].b]+=sz[fv];
                }
            }
            li[x].a=sz[s[x].b];li[x].b=s[x].a*sz[s[x].b];
        }
        sort(li+1,li+n+1,dmp);sort(q+1,q+Q+1,dmp);
        int j=1;
        int tp=0;
        for(int i=1;i<=n;i++){
            if(li[i].a==li[i+1].a&&li[i].b<=li[i+1].b)continue;
            while(tp>1&&C(l[tp-1],l[tp])>C(l[tp-1],li[i]))tp--;
            l[++tp]=li[i];
        }
        for(int i=1;i<=tp;i++){
            
            double cr;
            if(i<tp)cr=C(l[i],l[i+1]);
            else cr=1e7;
            for(;j<=Q&&(double)q[j].a<cr;j++)ans[q[j].b]=l[i].a*q[j].a+l[i].b;
        }
        for(int i=1;i<=Q;i++)printf("%lld
    ",ans[i]);
        return 0;
    }
    View Code

    拙者

    sol

    40% 贪心从前往后再从后往前取即可

    20% (1,2) 线段树维护最小值

    100%

    考虑第一次从左往右的修改。

    把+1看成向上,-1看成向下,这个序列看成折现

    每一个点的最终位置是他减他之前的最小值,也就是把他之前的最小值提到0(水平位置)。

    那么考虑维护区间最大值,最小值,极差,总和。

    从前往后是答案是 max(-最小值,0)

    从前往后是max(极差-(sum-Min))

    极差就是最高点,sum-Min为最后一个点的位置。

    60% 

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define maxn 200005
    #define mid ((l+r)>>1)
    #define ls k<<1
    #define rs k<<1|1
    using namespace std;
    int n,q,a[maxn],b[maxn];
    char ch[maxn];
    struct node{
        int v,bj;
    }tr[maxn*4];
    node wh(node A,node B){
        node C;
        C.sum=A.sum+B.sum;
        C.mi=min(A.mi,A.sum+B.mi);
        C.ma=max(A.ma,A.sum+B.ma);
        C.d=max(max(A.d,B.d),A.sum+B.ma-A.mi);
        return C;
    }
    void build(int k,int l,int r){
        if(l==r){tr[k].sum=tr[k].ma=tr[k].mi=a[l];tr[k].d=0;return;}
        build(ls,l,mid);build(rs,mid+1,r);
        tr[k]=wh(tr[ls],tr[rs]);
    }
    void upd(int k,int l,int r,int pl){
        if(l==r){
            tr[k].sum=tr[k].ma=tr[k].mi=a[l];
            return;
        }
        if(pl<=mid)upd(ls,l,mid,pl);
        else upd(rs,mid+1,r,pl);
        tr[k]=wh(tr[ls],tr[rs]);
    }
    node ask(int k,int l,int r,int li,int ri){
        if(l>=li&&r<=ri)return tr[k];
        if(ri<=mid)return ask(ls,l,mid,li,ri);
        if(li>mid)return ask(rs,mid+1,r,li,ri);
        return wh(ask(ls,l,mid,li,ri),ask(rs,mid+1,r,li,ri));
    }
    
    void wh(int k){
        tr[k].v=min(tr[ls].v,tr[rs].v);
    }
    void build(int k,int l,int r){
        if(l==r){tr[k].v=b[l];return;}
        build(ls,l,mid);build(rs,mid+1,r);
        wh(k);
    }
    void upd(int k,int v){
        tr[k].bj+=v;tr[k].v+=v;
    }
    void down(int k){
        if(tr[k].bj!=0){
            upd(ls,tr[k].bj);upd(rs,tr[k].bj);
            tr[k].bj=0;
        }
    }
    void add(int k,int l,int r,int li,int ri,int v){
        if(l>=li&&r<=ri){
            upd(k,v);return;
        }
        down(k);
        if(li<=mid)add(ls,l,mid,li,ri,v);
        if(ri>mid)add(rs,mid+1,r,li,ri,v);
        wh(k);
    }
    int ask(int k,int l,int r,int li,int ri){
        if(li==0)return 0;
        if(l>=li&&r<=ri)return tr[k].v;
        down(k);
        int Min=1e9;
        if(li<=mid)Min=min(Min,ask(ls,l,mid,li,ri));
        if(ri>mid)Min=min(Min,ask(rs,mid+1,r,li,ri));
        return Min;
    }
    int main()
    {
        cin>>n;scanf(" %s",ch+1);
        for(int i=1;i<=n;i++){
            a[i]=(ch[i]=='(')?1:-1;
        }
        if(n<=1000){
            scanf("%d",&q);
            for(int I=1,op,l,r;I<=q;I++){
                scanf("%d",&op);
                if(op==1)scanf("%d",&l),a[l]=-a[l];
                else {
                    scanf("%d%d",&l,&r);
                    if(op==2){
                        int tmp=0,ans=0;
                        for(int i=l;i<=r;i++){
                            b[i]=a[i];
                            if(tmp+b[i]<0)b[i]=0,ans++;
                            tmp+=b[i];
                        }
                        printf("%d
    ",ans);
                    }
                    else {
                        int tmp=0,ans=0;
                        for(int i=l;i<=r;i++){
                            b[i]=a[i];
                            if(tmp+b[i]<0)b[i]=0,ans++;
                            tmp+=b[i];
                        }
                        tmp=0;
                        for(int i=r;i>=l;i--){
                            if(tmp+b[i]<0)b[i]=0,ans++;
                            tmp+=b[i];
                        }
                        printf("%d
    ",ans);
                    }
                }
            }
        }
        else {
    
            for(int i=1;i<=n;i++)b[i]=b[i-1]+a[i];
            build(1,1,n);
            scanf("%d",&q);
            for(int I=1,op,l,r;I<=q;I++){
                scanf("%d",&op);
                if(op==1){
                    scanf("%d",&l),add(1,1,n,l,n,-2*a[l]);
                    a[l]=-a[l];
                }
                else {
                    scanf("%d%d",&l,&r);
                    if(op==2){
                        int x=ask(1,1,n,l-1,l-1),y=ask(1,1,n,l,r);
                        printf("%d
    ",max(x-y,0));
                    }
                }
            }
        }
        return 0;
    }
    View Code

    100%

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define mid ((l+r)>>1)
    #define ls k<<1
    #define rs k<<1|1
    #define maxn 200005
    using namespace std;
    int n,q,a[maxn];
    char ch[maxn];
    struct node{
        int ma,mi,sum,d;
    }tr[maxn*4];
    
    node wh(node A,node B){
        node C;
        C.sum=A.sum+B.sum;
        C.mi=min(A.mi,A.sum+B.mi);
        C.ma=max(A.ma,A.sum+B.ma);
        C.d=max(max(A.d,B.d),A.sum+B.ma-A.mi);
        return C;
    }
    void build(int k,int l,int r){
        if(l==r){tr[k].sum=a[l];tr[k].ma=max(a[l],0);tr[k].mi=min(a[l],0);tr[k].d=0;return;}
        build(ls,l,mid);build(rs,mid+1,r);
        tr[k]=wh(tr[ls],tr[rs]);
    }
    void upd(int k,int l,int r,int pl){
        if(l==r){
            tr[k].sum=a[l];tr[k].ma=max(a[l],0);tr[k].mi=min(a[l],0);tr[k].d=0;
            tr[k].d=0;
            return;
        }
        if(pl<=mid)upd(ls,l,mid,pl);
        else upd(rs,mid+1,r,pl);
        tr[k]=wh(tr[ls],tr[rs]);
    }
    node ask(int k,int l,int r,int li,int ri){
        if(l>=li&&r<=ri)return tr[k];
        if(ri<=mid)return ask(ls,l,mid,li,ri);
        if(li>mid)return ask(rs,mid+1,r,li,ri);
        return wh(ask(ls,l,mid,li,ri),ask(rs,mid+1,r,li,ri));
    }
    int main()
    {
        cin>>n;scanf(" %s",ch+1);
        for(int i=1;i<=n;i++){
            a[i]=(ch[i]=='(')?1:-1;
        }
        build(1,1,n);
        scanf("%d",&q);int tp=0;
        for(int I=1,op,l,r;I<=q;I++){
            scanf("%d",&op);
            if(op==1){
                scanf("%d",&l);a[l]=-a[l];
                upd(1,1,n,l);
            }
            else {
                scanf("%d%d",&l,&r);
                if(op==2){
                    node ans=ask(1,1,n,l,r);
                    printf("%d
    ",max(-ans.mi,0));
                }
                else {
                    node ans=ask(1,1,n,l,r);
                    int sum=max(-ans.mi,0)+max(ans.d-(ans.sum-ans.mi),0);
                    printf("%d
    ",sum);
                }
            }
        }
        return 0;
    }
    /*
    4
    (())
    1
    3 1 4
    */
    View Code

    注意事项:

    1.若查询l-1要特判0

    2.修改a[l]外面也要改

    3.区间最小值、最大值都要和0取,因为基准是0

  • 相关阅读:
    jQuery属性遍历、HTML操作
    jQuery效果函数
    【Solr初探】Solr安装,启动,查询,索引
    【mac osx安装opencv,python总结】
    反射给对象赋值——类型转换
    js 模拟a标签打开新网页
    MVC post 方法导出word文档
    Jquery ajax json 值回传不了
    商城
    批处理的赋值 调用 参数
  • 原文地址:https://www.cnblogs.com/liankewei/p/11714652.html
Copyright © 2011-2022 走看看