A
link
這個題是一個暴力
判斷是否全在對角線上或下,兩次二重迴圈即可,如果是,直接乘起來。
點選檢視程式碼
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mo = 1e9+7;
int n;
int a[805][805];
bool x(){
for(int i = 1;i <= n;++ i)
for(int j = 1;j < i;++ j){
if(a[i][j] != 0) return false;
}
return true;
}
bool s(){
for(int i = 1;i <= n;++ i)
for(int j = i+1;j <= n;++ j){
if(a[i][j] != 0) return false;
}
return true;
}
signed main(){
cin >> n;
for(int i = 1;i <= n;++ i)
for(int j = 1;j <= n;++ j)
cin >> a[i][j];
int ans = 1;
if(x()||s()){
for(int i = 1;i <= n;++ i){
ans *= a[i][i];
ans %= mo;
}
cout << ans;
}
else cout << "Arknights!";
return 0;
}
B
link
這個題和\(ABC347\)的\(c\)很像。
很顯然的一個性質,如果區間長度\(\geq T\),一定可以消滅。
不管是在哪個位置,對映到\(1\)~\(T\)(這時只剩長度\(\leq T\)的了)。
判斷那個位置能消耗的生命值最小,即可。
點選檢視程式碼
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,t,sum,ans;
int l[100005],r[100005],v[100005];
int cf[200005];
int cn;
signed main(){
cin >> n >> t;
for(int i = 1;i <= n;++ i){
cin >> l[i] >> r[i] >> v[i];
sum += v[i];
if(r[i]-l[i]+1 >= t){
cn += v[i];
continue;
}
int y = l[i];
l[i] %= t;
if(l[i] == 0) l[i] = t;
r[i] -= (y-l[i]);
r[i] = min(r[i],2*t);
cf[l[i]] += v[i];
cf[r[i]+1] -= v[i];
}
for(int i = 1;i <= 2*t;++ i)
cf[i] += cf[i-1];
for(int i = 1;i <= t;++ i)
ans = max(ans,cf[i]+cf[i+t]);
ans += cn;
ans = sum-ans;
cout << ans;
return 0;
}
C
link
這個題很有意思。
他雖然說是區間長度大於等於\(k\),但其實最優區間長度一定可以等於\(k\)。
於是只需要用單調佇列求最大最小值即可。
關於為什麼最優區間長度一定可以等於\(k\)。
設已經等於\(k\)了,考慮向右增大區間。
如果讓最大值更大了,肯定更好,但是如果讓最小值變小了,不好。
考慮如果讓最大值更大了,我們可以把左邊也增大,最小值可能還會變小,很好。
所以最優區間長度一定可以等於\(k\)。
點選檢視程式碼
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,k;
int a[100005];
int xq[100005];
int nq[100005];
int hx = 1,hn = 1,tx,tn;
int ans = -1e18;
void pux(int x){
while(a[xq[tx]] > a[x]&&hx <= tx) tx--;
xq[++tx] = x;
}
void pun(int x){
while(a[nq[tn]] < a[x]&&hn <= tn) tn--;
nq[++tn] = x;
}
signed main(){
cin >> n >> k;
for(int i = 1;i <= n;++ i)
cin >> a[i];
for(int i = 1;i < k;++ i)
pux(i),pun(i);
for(int i = k;i <= n;++ i){
if(xq[hx] <= i-k) hx++;
if(nq[hn] <= i-k) hn++;
pux(i),pun(i);
ans = max(ans,a[xq[hx]]+a[nq[hn]]);
}
cout << ans;
return 0;
}
D
link
這個題是二分,考慮二分最大的費用,那麼每一個數到這個價值都是一個一定大小的區間,只要看看所有的區間夠不夠所有區間即可。
\(check\)函式是\(O(n)\)的。
最後算答案是可以看出,多出的區間一定是多算了最大費用,減去即可。
點選檢視程式碼
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,L;
int v[100005];
int check(int x){
int sum = 0;
for(int i = 1;i <= n;++ i){
int d = x/v[i];
sum += d;
}
return sum;
}
signed main(){
cin >> n >> L;
for(int i = 1;i <= n;++ i)
cin >> v[i];
sort(v+1,v+1+n);
int l = 0ll,r = 1e18,md;
while(l < r){
md = (l+r)/2;
if(check(md) >= L) r = md;
else l = md+1;
}
int sum = 0;
for(int i = 1;i <= n;++ i){
int d = r/v[i];
sum += v[i]*d*(d+1)/2;
}
int q = check(r);
int e = q-L;
sum -= e*r;
cout << sum;
return 0;
}