• 【bzoj3441】乌鸦喝水


    Source

    bzoj3441

    Hint

    请先思考后再展开

    按被删除的顺序考虑每个点,然后按照题意模拟

    Solution

    请先思考后再展开

    被删除的顺序一定是按照【能被操作的次数】为第一关键字,位置作为第二关键字
    然后你维护当前轮数和当前走到什么位置(我存了具体位置,其实应该存排名更好写……)
    用个树状数组资瓷排名和位置之间的转化即可
    时间复杂度为 $O(nlogn)$

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    #include<ctime>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<map>
    #include<set>
    #include<queue>
    #include<deque>
    #include<stack>
    #include<bitset>
    #include<vector>
    #include<algorithm>
    #include<iostream>
    #include<deque>
    using namespace std;
    namespace mine
    {
    typedef long long ll;
    #define double long double
    const int INF=0x3f3f3f3f;
    ll ()
    {
    ll ans=0;char c=getchar();int f=1;
    while(c<'0' or c>'9') {if(c=='-') f=-1;c=getchar();}
    while('0'<=c and c<='9') ans=ans*10+c-'0',c=getchar();
    return ans*f;
    }
    void write(ll num)
    {
    if(num<0) {num=-num;putchar('-');}
    if(num>9) write(num/10);
    < 大专栏  【bzoj3441】乌鸦喝水div class="line"> putchar('0'+num%10);
    }
    void writeln(int num){write(num);puts("");}
    #define FR first
    #define SE second
    #define MP make_pair
    #define pr pair<ll,ll>
    #define PB push_back
    inline void chmax(ll &x,ll y) {x=x>y?x:y;}
    inline void chmin(ll &x,ll y) {x=x<y?x:y;}
    const int MAX_N=1e5+10;
    int bin[30];
    struct BIT
    {
    int bit[MAX_N];BIT(){memset(bit,0,sizeof bit);}
    int lowbit(int x) {return x&-x;}
    void add(int x,int c) {while(x<MAX_N) bit[x]+=c,x+=lowbit(x);}
    int ask(int x) {int ans=0;while(x>=1) ans+=bit[x],x-=lowbit(x);return ans;}
    int findk(int k)
    {
    int ans=0;
    for(int i=20;i>=0;i--) if(ans+bin[i]<MAX_N and k>=bit[ans+bin[i]]) k-=bit[ans+bin[i]],ans+=bin[i];
    return ans;
    }
    }bit;
    pr a[MAX_N];
    void main()
    {
    bin[0]=1;for(int i=1;i<30;i++) bin[i]=bin[i-1]<<1;
    int n,m,all;scanf("%d%d%d",&n,&m,&all);
    for(int i=1;i<=n;i++) a[i].FR=all-qread()+1;
    for(int i=1;i<=n;i++) a[i].FR=ceil((double)a[i].FR/qread()),a[i].SE=i,bit.add(i,1);
    sort(a+1,a+n+1);
    ll ans=0,dec=0;int turn=1,pos=1;//pos=应从哪里开始
    for(int i=1;i<=n and turn<=m;i++)
    {
    int rk=bit.ask(pos);
    ll tmp=a[i].FR-dec;int me=bit.ask(a[i].SE);
    if(tmp>0)
    {
    int rk2=(tmp+rk-1)%(n-i+1),t2=(tmp+rk-1)/(n-i+1);
    if(rk2==0) rk2=n-i+1,t2--;
    if(turn+t2>m) {ans+=ll(m-turn)*(n-i+1)+(n-i+1-rk+1);break;}
    turn+=t2;dec+=tmp;ans+=tmp;
    if((me==n-i+1 and rk2==n-i) or rk2==n-i+1) rk2=1,turn++;
    else if(rk2<me) rk2++;
    bit.add(a[i].SE,-1);
    pos=bit.findk(rk2);
    }
    else
    {
    if(rk>me) rk--;
    if(rk==n-i+1) rk=1,turn++;
    bit.add(a[i].SE,-1);
    pos=bit.findk(rk);
    }
    }
    printf("%lld",ans);
    }
    };
    int main()
    {
    srand(time(0));
    mine::main();
    }

  • 相关阅读:
    课后作业07--二分法查找算法代码
    检索03 -- 二分法查找
    课堂随笔05--冒泡排序
    课后作业 06 -- 小数后几位精确判断并输出
    课后作业 05 -- 输出一段带字母与数字的随机数
    课后作业 04 --DateTime应用,判断多久后生日之类
    检索02--随机数种子的一些概念和理解
    课堂随笔04--关于string类的一些基本操作
    P1174 互素
    P1001 第K极值
  • 原文地址:https://www.cnblogs.com/lijianming180/p/12286316.html
Copyright © 2020-2023  润新知