生活随笔
收集整理的這篇文章主要介紹了
牛客练习赛 68
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
A.牛牛的mex
n,q≤105,0≤ai<n且ai互不相同n,q≤10 ^5,0≤a i<n 且 a_i互不相同n,q≤105,0≤ai<n且ai?互不相同
后面兩個條件非常重要,通過后面兩個條件將問題轉化為一個區間內最小未出現的自然數就等于不在這個區間內最小出現的自然數對于區間[l,r][l,r][l,r]只需要算出[1,l?1]和[r+1,n][1,l-1]和[r+1,n][1,l?1]和[r+1,n]區間最小出現的自然數即可。直接預處理前綴后綴注意邊界由于0≤ai<n0\leq a_i<n0≤ai?<n只需讓pre[0]=suc[n+1]=n即可
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std
;
const int N
=100010;
int a
[N
],pre
[N
],suc
[N
];
int n
,q
;
int main()
{cin
>>n
>>q
;pre
[0]=suc
[n
+1]=n
;for(int i
=1;i
<=n
;i
++) cin
>>a
[i
];for(int i
=1;i
<=n
;i
++) pre
[i
]=min(pre
[i
-1],a
[i
]);for(int i
=n
;i
;i
--) suc
[i
]=min(suc
[i
+1],a
[i
]);while(q
--){int l
,r
;cin
>>l
>>r
;cout
<<min(pre
[l
-1],suc
[r
+1])<<'\n';}return 0; }
由于日常眼瞎非常容易看不見上述重要條件,因此不如上優雅暴力——莫隊
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std
;
const int N
=100010;
int cnt
[N
],sz
,pos
[N
];
struct node
{int l
,r
,id
;bool operator<(const node
& o
) const {if(pos
[l
]==pos
[o
.l
]) return r
<o
.r
;else return pos
[l
]<pos
[o
.l
];}
}q
[N
];
int a
[N
],n
,m
;
int ans
[N
],res
;
void add(int k
)
{cnt
[a
[k
]]++;while(cnt
[res
]) res
++;
}
void sub(int k
)
{cnt
[a
[k
]]--;if(!cnt
[a
[k
]]&&a
[k
]<=res
) res
=a
[k
];
}
int main()
{cin
>>n
>>m
;sz
=sqrt(n
);for(int i
=1;i
<=n
;i
++){cin
>>a
[i
];pos
[i
]=i
/sz
;}for(int i
=1;i
<=m
;i
++){cin
>>q
[i
].l
>>q
[i
].r
;q
[i
].id
=i
;}sort(q
+1,q
+1+m
);int l
=1,r
=0;for(int i
=1;i
<=m
;i
++){while(l
<q
[i
].l
) sub(l
++);while(l
>q
[i
].l
) add(--l
);while(r
<q
[i
].r
) add(++r
);while(r
>q
[i
].r
) sub(r
--);ans
[q
[i
].id
]=res
;}for(int i
=1;i
<=m
;i
++) cout
<<ans
[i
]<<'\n';return 0;
}
B.牛牛的算術
發現當 n≥199999n \geq 199999n≥199999 時答案必為000。
于是我們只需要預處理 n<199999n < 199999n<199999的答案即可。
預處理前綴和和前綴積直接算答案。
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std
;
typedef long long ll
;
const int N
=200010;
const ll mod
=199999;
ll s1
[N
],s2
[N
];
string p
="199999";
void init()
{for(int i
=1;i
<mod
;i
++)s1
[i
]=(s1
[i
-1]+1ll*i
*(i
+1)/2*i
%mod
)%mod
;s2
[0]=1;for(int i
=1;i
<mod
;i
++)s2
[i
]=s2
[i
-1]*i
%mod
*s1
[i
]%mod
;
}
int main()
{int T
=1;init();cin
>>T
;while(T
--){string a
;cin
>>a
;if(a
.size()>6||a
.size()==6&&a
>p
){cout
<<0<<'\n';continue;}reverse(a
.begin(),a
.end());int base
=1,n
=0;for(auto t
:a
){n
+=base
*int(t
-'0');base
*=10;}cout
<<s2
[n
]<<'\n';}return 0; }
C.牛牛的無向圖
不難看出所求就是通過長度不大于L的邊相互可達點的數量
對于大于L的邊我們可以看作無這條邊,我們用并查集維護連通塊點的數量。
把詢問和邊放在一起排序然后處理即可
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std
;
typedef long long ll
;
const int N
=100010,M
=500010;
struct node
{int op
;int a
,b
,w
;int id
;bool operator<(const node
& o
)const {if(w
==o
.w
) return op
<o
.op
;return w
<o
.w
;}
}e
[2*M
];
int n
,m
;
int q
[M
],k
;
ll ans
[M
],now
;
unsigned int SA
, SB
, SC
; int LIM
;
unsigned int rng61(){SA
^= SA
<< 16;SA
^= SA
>> 5;SA
^= SA
<< 1;unsigned int t
= SA
;SA
= SB
;SB
= SC
;SC
^= t
^ SA
;return SC
;
}
void gen(){scanf("%d%d%d%u%u%u%d", &n
, &m
, &k
, &SA
, &SB
, &SC
, &LIM
);for(int i
= 1; i
<= m
; i
++){e
[i
].a
= rng61() % n
+ 1;e
[i
].b
= rng61() % n
+ 1;e
[i
].w
= rng61() % LIM
;}for(int i
= 1; i
<= k
; i
++){q
[i
] = rng61() % LIM
;}
}
int p
[N
],sz
[N
];
int find(int x
)
{return x
==p
[x
]?x
:p
[x
]=find(p
[x
]);
}
int main()
{gen();for(int i
=1;i
<=m
;i
++) e
[i
].op
=1;for(int i
=1;i
<=n
;i
++) p
[i
]=i
,sz
[i
]=1;for(int i
=1;i
<=k
;i
++){e
[i
+m
].op
=2;e
[i
+m
].w
=q
[i
];e
[i
+m
].id
=i
;}sort(e
+1,e
+1+m
+k
);for(int i
=1;i
<=m
+k
;i
++){if(e
[i
].op
==1){int pa
=find(e
[i
].a
),pb
=find(e
[i
].b
);if(pa
!=pb
){p
[pa
]=pb
;now
+=1ll*sz
[pa
]*sz
[pb
];sz
[pb
]+=sz
[pa
];}}elseans
[e
[i
].id
]=now
;}ll res
=0;for(int i
=1;i
<=k
;i
++) res
^=ans
[i
];cout
<<res
<<'\n';return 0;
}
??途W的題目感覺挺不錯的,但是評測機就很讓人落淚啊
要加油哦~
總結
以上是生活随笔為你收集整理的牛客练习赛 68的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。