zoukankan      html  css  js  c++  java
  • 冬季训练8 AB题题解

    A题 

    题目大意:给出一个1~n的排列,现在要求选择一个合适的分割点,将整个排列分为两个部分,要求通过适当的移动使得前半部分的所有数值都小于后半部分的数值,现在给出移动每个数字所花费的代价,输出最小代价

    这题显然对于左集合若最后的个数为k,那值必定为1-k,右集合值为k+1-n;所以最朴素的方法就是枚举每个分割点,再枚举左集合的k值,再O(n)遍历出需要转移的价值,取min,复杂度O(n3)

    思考一下如果我们处理出权值从1到n的转移价值前缀和,当分割点从左往右移的过程中,若右区间划分出来的值为a[i],即当你枚举的k<a[i],对于前一次划分,你需要多承担将a[i]移到右集合的价值,对于k>a[i]的情况你可以少承担从右集合移到左集合的价值,可以将值O(1)转移,O(n2);

    在思考一下线段树维护每个k点当前划分的值,区间更新划分的影响全局取min,复杂度O(nlogn);

    
    
     1 #include<stdio.h>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<bitset>
     7 #include<set>
     8 #include<deque>
     9 #include<queue>
    10 #include<vector>
    11 //#include<unordered_map>
    12 #include<map>
    13 #include<stack>
    14 using namespace std;
    15 #define ll long long
    16 #define ull unsigned long long
    17 #define pii pair<int,int>
    18 #define Pii pair<ll,ll>
    19 #define m_p make_pair
    20 #define l_b lower_bound
    21 #define u_b upper_bound 
    22 const int inf=0x3f3f3f3f;
    23 const ll linf=0x3f3f3f3f3f3f3f3f;
    24 const int maxn=2e5+11;
    25 const int maxm=1e3+11;
    26 const int mod=1e9+7; 
    27 inline ll rd() {ll res, ch=0;while(!(ch>='0'&&ch<='9')) ch=getchar();res=ch-'0';while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-'0';return res;}
    28 inline ll qpow(ll a,ll b){ll res=1;while(b){if(b&1){res*=a;res%=mod;}b>>=1;a=a*a%mod;}return res;}
    29 inline ll gcd(ll a,ll b){if(b==0) return a;return gcd(b,a%b);}
    30 //iterator 
    31 //head
    32 ll tree[maxn<<2],lazy[maxn<<2];
    33 ll sum[maxn],a[maxn],b[maxn];
    34 inline ll read() {
    35     ll res, ch=0;
    36     while(!(ch>='0'&&ch<='9')) ch=getchar();
    37     res=ch-'0';
    38     while((ch=getchar())>='0'&&ch<='9')
    39         res=res*10+ch-'0';
    40     return res;
    41 }
    42 void pushdown(int rt) {
    43     if(lazy[rt]) {
    44         tree[rt<<1]+=lazy[rt];
    45         tree[rt<<1|1]+=lazy[rt];
    46         lazy[rt<<1]+=lazy[rt];
    47         lazy[rt<<1|1]+=lazy[rt];
    48         lazy[rt]=0;
    49     }
    50 }
    51 void build(int rt,int l,int r) {
    52     lazy[rt]=0;
    53     if(l==r) {
    54         tree[rt]=sum[l];
    55         return;
    56     }
    57     int mid=l+r>>1;
    58     build(rt<<1,l,mid);
    59     build(rt<<1|1,mid+1,r);
    60     tree[rt]=min(tree[rt<<1],tree[rt<<1|1]);
    61 }
    62 void update(int rt,int l,int r,int tl,int tr,int k) {
    63     if(l==tl&&r==tr) {
    64         lazy[rt]+=k;
    65         tree[rt]+=k;
    66         return;
    67     }
    68     pushdown(rt);
    69     int mid=l+r>>1;
    70     if(mid>=tr) {
    71         update(rt<<1,l,mid,tl,tr,k);
    72     } else if(tl>mid) {
    73         update(rt<<1|1,mid+1,r,tl,tr,k);
    74     } else {
    75         update(rt<<1,l,mid,tl,mid,k);
    76         update(rt<<1|1,mid+1,r,mid+1,tr,k);
    77     }
    78     tree[rt]=min(tree[rt<<1],tree[rt<<1|1]);
    79 }
    80 int main() {
    81     int n=read();
    82     for(int i=1; i<=n; i++) a[i]=read();
    83     for(int i=1; i<=n; i++) {
    84         b[i]=read();
    85         sum[a[i]]=b[i];
    86     }
    87     for(int i=2; i<=n; i++) sum[i]+=sum[i-1];
    88     build(1,1,n);
    89     ll ans=min(b[1],b[n]);
    90     for(int i=1; i<n; i++) {
    91         if(a[i]!=1) update(1,1,n,1,a[i]-1,b[i]);
    92         update(1,1,n,a[i],n,-b[i]);
    93         ans=min(ans,tree[1]);
    94     }
    95     printf("%lld
    ",ans);
    96 }
     

    B题

    在前面开m个0,学到了

    https://blog.csdn.net/weixin_44178736/article/details/104009340

    菜鸡不会树状数组,附送大家一份权值线段树代码

    还有莫队的解法大家自行百度

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn=6e5+11;
    struct Tree {
        int l,r,val;
    } tree[maxn<<2];
    int l[maxn],r[maxn],pos[maxn],a[maxn];
    int n,m;
    void pushup(int rt) {
        tree[rt].val=tree[rt<<1].val+tree[rt<<1|1].val;
    }
    void build(int rt,int l,int r) {
        tree[rt].l=l;
        tree[rt].r=r;
        if(l==r) {
            if(l>m) tree[rt].val=1;
            else tree[rt].val=0;
            return;
        }
        int mid=l+r>>1;
        build(rt<<1,l,mid);
        build(rt<<1|1,mid+1,r);
        pushup(rt);
    }
    void update(int rt,int p,int f) {
        if(tree[rt].l==tree[rt].r) {
            if(!f) tree[rt].val=0;
            else tree[rt].val=1;
            return;
        }
        int mid=tree[rt].l+tree[rt].r>>1;
        if(p<=mid) {
            update(rt<<1,p,f);
        } else update(rt<<1|1,p,f);
        pushup(rt);
    }
    void query(int rt,int now,int p,int x) {
        if(tree[rt].l==tree[rt].r) {
            r[x]=max(r[x],now+1);
            return;
        }
        int mid=tree[rt].l+tree[rt].r>>1;
        if(mid<p) {
            now+=tree[rt<<1].val;
            query(rt<<1|1,now,p,x);
        } else query(rt<<1,now,p,x);
    }
    int main() {
        cin>>n>>m;
        for(int i=1; i<=n; i++) pos[i]=i+m,l[i]=i,r[i]=i;
        int pre=m;
        for(int i=1; i<=m; i++) cin>>a[i];
        build(1,1,n+m);
        for(int i=1; i<=m; i++) {
            l[a[i]]=1;
            query(1,0,pos[a[i]],a[i]);
            //r[a[i]]=max(r[a[i]],pos[a[i]]-m);
            update(1,pos[a[i]],0);
            update(1,pre,1);
            pos[a[i]]=pre;
            pre--;
        }
        for(int i=1; i<=n; i++) query(1,0,pos[i],i);
        for(int i=1; i<=n; i++) cout<<l[i]<<' '<<r[i]<<endl;
    }
  • 相关阅读:
    Silverlight开发“慢”游美丽的分形世界(画分形2)
    c#进阶methods中3explicit和implicit
    C#进阶可选参数和命名参数
    Silverlight杂记自定义loading
    c#进阶params可变个数的参数
    Abundant Resources
    欧拉函数
    容斥原理 讲解
    sdut 2497 A simple problem (并查集 or dfs)
    hdu 4366 Card Collector (容斥原理)
  • 原文地址:https://www.cnblogs.com/tinkerx/p/12262946.html
Copyright © 2011-2022 走看看