【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();
}

猜你喜欢

转载自www.cnblogs.com/lijianming180/p/12286316.html