這可能是我做以來做的最好的一次?它居然了!哼╭(╯^╰)╮不給力的服務器!關鍵時刻拓機!雖然這次的D比較水。但是是我一次過了四題QAQ…
比賽傳送門:https://codeforces.com/contest/1106
A. Lunar New Year and Cross Counting
題解:數交叉個數,枚舉中點即可。
代碼
#include<bits/stdc++.h>
using namespace std;
string s[505];
int n;
int count1(int x,int y)
{
if(s[x][y] != 'X') return 0;
int dir[4][2] = {-1,-1,-1,1,1,-1,1,1};
for(int i = 0; i < 4; ++i) {
int tx = x + dir[i][0];
int ty = y + dir[i][1];
if(tx < 0 || tx >= n || ty < 0 || ty >= n)
return 0;
if(s[tx][ty] != 'X') return 0;
}
return 1;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.in","r",stdin);
#endif
cin >> n;
for(int i = 0; i < n; ++i) {
cin >> s[i];
}
int ans = 0;
for(int i = 0; i < n; ++i) {
for(int j = 0; j < n; ++j) {
ans += count1(i,j);
}
}
cout << ans << endl;
return 0;
}
B. Lunar New Year and Food Ordering
題解:按題意模擬,用一個優先隊列維護當前最便宜並且最小的食物,如果當前顧客所需要的食物數量不夠,那就取出來最便宜的食物,直到滿足當前顧客,如果滿足不了那就輸出;如果足夠當前顧客需要的,那就直接輸出數量乘以花費即可。(千萬要注意會爆long long!!)
代碼
#include<bits/stdc++.h>
using namespace std;
const int N = 1E5+10;
struct node{
int t,d;
}cust[N];
struct food{
int c,d,id;
bool operator < (const food & u) const {
if(d == u.d) {
return id > u.id;
}
return d > u.d;
}
};
priority_queue<food> pq;
int c[N],d[N];
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.in","r",stdin);
#endif
int n,m;
cin >> n >> m;
for(int i = 0; i < n; ++i) {
scanf("%d",&c[i]);
}
for(int i = 0; i < n; ++i) {
scanf("%d",&d[i]);
}
for(int i = 0; i < n; ++i) {
pq.push(food{c[i],d[i],i});
}
for(int i = 0; i < m; ++i) {
scanf("%d%d",&cust[i].t,&cust[i].d);
cust[i].t--;
}
long long tmp = 0;
for(int i = 0; i < m; ++i) {
tmp = 0;
int t = cust[i].t;
int num = cust[i].d;
if(num > c[t]) {
tmp += 1LL * d[t] * c[t];
num -= c[t];
c[t] = 0;
if(pq.empty()) tmp = -1;
while(!pq.empty()) {
if(tmp == -1) break;
food cur = pq.top(); pq.pop();
cur.c = min(cur.c,c[cur.id]);
if(cur.c >= num) {
tmp += 1LL * cur.d * num;
cur.c -= num;
c[cur.id] -= num;
if(cur.c != 0)
pq.push(cur);
break;
}else{
tmp += 1LL * cur.c * cur.d;
num -= cur.c;
c[cur.id] = 0;
}
if(pq.empty()) tmp = -1;
}
}else{
c[t] -= num;
tmp += 1LL * d[t] * num;
}
if(tmp == -1) tmp = 0;
cout << tmp << endl;
}
return 0;
}
C. Lunar New Year and Number Division
說實話這題當時純靠莽…,題意是給偶數個數,然後分組,每組至少兩個,最後求最小化,爲第組的數字的和,一共有組。既然要最小化和,那麼就要最小化,我當時就猜測,肯定每組兩個數,讓每組最小的話肯定是最小和最大配,第二小和第二大配。然後莽了一發就A了。
題解:我們可以考慮兩個數,,答案只能是四個數,分一組分兩組
對比顯然每組的數量越少,總和越小。我們再觀察,拆開:
如果我們想要儘可能的小,那麼我們就需要最小化和,由乘法的性質可得讓和儘可能大即可。因此我們可以證明最小的和最大的配,第二小和第二大的配,以此類推的做法是正確的。
代碼
#include<bits/stdc++.h>
using namespace std;
const int N = 3E5+10;
long long a[N];
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.in","r",stdin);
#endif
int n;
cin >> n;
for(int i = 0; i < n; ++i) {
scanf("%lld",&a[i]);
}
sort(a,a+n);
long long sum = 0;
for(int i = 0; i < n / 2; ++i) {
sum += (a[i] + a[n - i - 1]) * (a[i] + a[n - i - 1]);
}
cout << sum << endl;
return 0;
}
D. Lunar New Year and a Wander
題解:既然要訪問的路徑字典序最小,那麼我們用優先隊列+bfs就可以很好解決了。
代碼
#include<bits/stdc++.h>
#define P pair<int,int>
using namespace std;
const int N = 1E5+10;
//vector<int> e[N];
priority_queue<int,vector<int>,greater<int> > e[N];
bool vis[N];
vector<int> ans;
priority_queue<int,vector<int>,greater<int> > pq;
void bfs()
{
pq.push(1);
vis[1] = 1;
ans.push_back(1);
while(!pq.empty()) {
int cur = pq.top();
if(vis[cur] == 0) {
vis[cur] = 1;
ans.push_back(cur);
}
pq.pop();
for(; !e[cur].empty(); e[cur].pop()) {
int v = e[cur].top();
pq.push(v);
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.in","r",stdin);
#endif
int n,m,x,y;
cin >> n >> m;
for(int i = 0; i < m; ++i) {
scanf("%d%d",&x,&y);
e[x].push(y);
e[y].push(x);
}
bfs();
int len = ans.size();
for(int i = 0; i < len; ++i) {
printf("%d%c",ans[i],i==len-1?'\n':' ');
}
return 0;
}
E. Lunar New Year and Red Envelopes
題意:在每個時間段內搶紅包,只要在當前時間可以搶紅包,那麼他就一定會去搶。然後沒搶完一個紅包,那麼他必須等到時間才能搶下一個紅包。期間最多可以次阻撓 在時間時搶紅包。問最少可以獲得多少紅包。
題解:我們可以將問題分爲兩個部分,沒有阻撓,所能獲得的最少收益。和有不超過次時間點阻撓最少所能獲得的收益。
那麼第一部分是可以通過優先隊列預處理出來的,同時我們記錄每個時間點的收益,和下一次搶紅包的時間點。然後對於不超過次的阻撓,我們可以用動態規劃來解決。表示在時間時次阻撓最少所能獲得的收益。我們發現狀態的轉移有和兩種,並且每次搶完紅包必須等到才能搶,也就意味着下一次搶紅包時間是大於你的決策時的時間的,因此我們不妨考慮倒過來轉移。(實際上正着來也是可以的,而且官方題解是用的滾動數組)就有
最後答案就是。
代碼
#include<bits/stdc++.h>
typedef long long LL;d
using namespace std;
const int N = 1E5+10;
struct node{
int s,t,d,w;
bool operator < (const node & u) const{
if(w == u.w) return d < u.d;
return w < u.w;
}
};
bool cmp(const node & a, const node & b){ return a.s < b.s; }
priority_queue<node> pq;
vector<node> v;
LL dp[N][201], got[N], nxt[N];
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.in","r",stdin);
#endif
int n,m,k,s,t,d,w;
cin >> n >> m >> k;
for(int i = 0; i < k; ++i) {
cin >> s >> t >> d >> w;
v.push_back(node{s,t,d,w});
}
sort(v.begin(),v.end(),cmp);
int cur = 0;
//1 4
//6 4 + 7
//11 4 + 7 + 9 <!> 11 <!>12 --> 4 + 7 = 11
for(int i = 1; i <= n; ++i) {
while(cur < k && v[cur].s <= i)
pq.push(v[cur++]);
while(!pq.empty() && pq.top().t < i) pq.pop();
if(!pq.empty()){
node t = pq.top();
got[i] = t.w;
nxt[i] = t.d + 1;
}else{
got[i] = 0;
nxt[i] = i + 1;
}
}
memset(dp,0x3f,sizeof dp);
dp[n + 1][0] = 0;
for(int i = n; i > 0; --i) {
dp[i][0] = dp[nxt[i]][0] + got[i];
}
for(int i = n; i >= 1; --i) {
for(int j = 0; j <= m; ++j) {
dp[i][j] = min(dp[i][j], dp[nxt[i]][j] + got[i]);
dp[i][j] = min(dp[i][j], dp[i + 1][j - 1]);
}
}
LL ans = *min_element(dp[1],dp[2]);
cout << ans << endl;
return 0;
}