A - Bad Triangle
選出三個序列使之不能組成三角形。先把差距最大的選了,枚舉中間值。兩邊之和不大于第三邊。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include<iostream>
#include<algorithm>
using namespace std
;
const int N
=50010;
int a
[N
];
int main()
{IO
;int T
;cin
>>T
;while(T
--){int n
;cin
>>n
;for(int i
=1;i
<=n
;i
++) cin
>>a
[i
];int i
;for(i
=2;i
<n
;i
++) if(a
[1]+a
[i
]<=a
[n
])break;if(i
==n
) cout
<<-1<<endl
;else cout
<<1<<' '<<i
<<' '<<n
<<endl
;}return 0;
}
B - Substring Removal Game
第一次沒加#include<vector>還Compilation error了。。
考慮原串中連續的1。兩人一定輪流選擇目前連續1個數最多的。把連續的1個數存到一個數組,逆序。兩人輪流取即可。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std
;
const int N
=110;
int a
[N
];
int main()
{IO
;int T
;cin
>>T
;while(T
--){string s
;cin
>>s
;int n
=s
.size();vector
<int> ans(n
);for(int i
=1;i
<=n
;i
++) a
[i
]=s
[i
-1]-'0';for(int i
=1;i
<=n
;i
++){int j
=i
;while(j
<=n
&&a
[i
]==a
[j
]) j
++;if(a
[i
]==1) ans
.push_back(j
-i
);i
=j
-1;}int res
=0;sort(ans
.begin(),ans
.end());reverse(ans
.begin(),ans
.end());for(int i
=0;i
<ans
.size();i
++) if(i
%2==0) res
+=ans
[i
];cout
<<res
<<endl
;}return 0;
}
C - Good Subarrays
對于原數組a[l+1]+a[l+2]+?+a[r]=r?l+1a[l+1]+a[l+2]+\dots+a[r]=r-l+1a[l+1]+a[l+2]+?+a[r]=r?l+1考慮前綴和數組即a[r]?a[l]=r?la[r]-a[l]=r-la[r]?a[l]=r?l變換一下a[r]?r=a[l]?la[r]-r=a[l]-la[r]?r=a[l]?l。因此只需統計a[i]?ia[i]-ia[i]?i的個數,根據組合數的計算公式即可。由于可能有負數弄了個map映射。上述情況未考慮i=0的情況,因此最后應加上a[i]==i的個數。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include<cstdio>
#include<string>
#include<map>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std
;
typedef long long ll
;
typedef pair
<int,int> pii
;
const int N
=100010;
int a
[N
];
map
<int,int> mp
;
int idx
=0;
int get(int s
)
{if(!mp
.count(s
)) mp
[s
]=++idx
;return mp
[s
];
}
ll cnt
[N
];
int main()
{IO
;int T
;cin
>>T
;while(T
--){int n
;cin
>>n
;mp
.clear();for(int i
=0;i
<=n
;i
++) cnt
[i
]=0;idx
=0;string s
;cin
>>s
;for(int i
=1;i
<=n
;i
++) a
[i
]=s
[i
-1]-'0';for(int i
=1;i
<=n
;i
++) a
[i
]+=a
[i
-1];for(int i
=1;i
<=n
;i
++) cnt
[get(a
[i
]-i
)]++;ll res
=0;for(int i
=1;i
<=idx
;i
++) res
+=1ll*cnt
[i
]*(cnt
[i
]-1)/2;for(int i
=1;i
<=n
;i
++)if(a
[i
]==i
) res
++;cout
<<res
<<endl
;}return 0;
}
這題很快就想到怎么寫了,但是碼代碼能力還是不行寫了半天。最開始沒想用map弄明白數組開多大煩死了(負數可以平移)然后就用map了。看群里討論發現負數不一定平移,可以為負數多開一個數組記錄a[-i],i<0。
D - Colored Rectangles
首先貪心,對于每一對木條,肯定選擇長的。因此先降序排列數組。
f[i][j][k]表示:R用了i個,G用了j個,B用了k個的集合。轉移考慮最后用的是那一對木棒。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include<cstdio>
#include<string>
#include<map>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std
;
typedef long long ll
;
typedef pair
<int,int> pii
;
const int N
=210;
int a
[N
],b
[N
],c
[N
];
int f
[N
][N
][N
];
int cnta
,cntb
,cntc
;
int main()
{IO
;cin
>>cnta
>>cntb
>>cntc
;for(int i
=1;i
<=cnta
;i
++) cin
>>a
[i
];for(int i
=1;i
<=cntb
;i
++) cin
>>b
[i
];for(int i
=1;i
<=cntc
;i
++) cin
>>c
[i
];sort(a
+1,a
+1+cnta
);sort(b
+1,b
+1+cntb
);sort(c
+1,c
+1+cntc
);reverse(a
+1,a
+1+cnta
);reverse(b
+1,b
+1+cntb
);reverse(c
+1,c
+1+cntc
);
for(int i
=0;i
<=cnta
;i
++)for(int j
=0;j
<=cntb
;j
++)for(int k
=0;k
<=cntc
;k
++){if(i
&&j
&&(i
+j
+k
)%2==0) f
[i
][j
][k
]=max(f
[i
][j
][k
],f
[i
-1][j
-1][k
]+a
[i
]*b
[j
]);if(j
&&k
&&(i
+j
+k
)%2==0) f
[i
][j
][k
]=max(f
[i
][j
][k
],f
[i
][j
-1][k
-1]+c
[k
]*b
[j
]);if(i
&&k
&&(i
+j
+k
)%2==0) f
[i
][j
][k
]=max(f
[i
][j
][k
],f
[i
-1][j
][k
-1]+a
[i
]*c
[k
]);}int res
=0;for(int i
=0;i
<=cnta
;i
++) res
=max(res
,f
[i
][cntb
][cntc
]);for(int i
=0;i
<=cntb
;i
++) res
=max(res
,f
[cnta
][i
][cntc
]);for(int i
=0;i
<=cntc
;i
++) res
=max(res
,f
[cnta
][cntb
][i
]);cout
<<res
<<endl
;return 0;
}
D題最后1分鐘提交的太驚險了。
E-Two Types of Spells
群里大佬說是權值線段樹+離散化,這個我學過補一下吧。
如果有k個lightning,那么能過翻倍k-1或者k個傷害(討論一下),翻倍肯定翻倍最大的幾個,因此考慮權值線段樹(因此需要離散化)維護前k大,一般有刪除加入需要用set維護,數據無重復,讓題目簡單不少。
lower_bound只能夠在升序情況下使用
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include<cstdio>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std
;
typedef long long ll
;
typedef pair
<int,int> pii
;
const int N
=200010;
int n
;
pii q
[N
];
vector
<int> id
;
struct node
{int l
,r
,cnt
;ll sum
;
}tree
[N
*4];
int get(int a
)
{int l
=0,r
=id
.size()-1;while(l
<r
){int mid
=l
+r
>>1;if(id
[mid
]<=a
) r
=mid
;else l
=mid
+1;}return l
+1;
}
void pushup(int u
)
{tree
[u
].cnt
=tree
[u
<<1].cnt
+tree
[u
<<1|1].cnt
;tree
[u
].sum
=tree
[u
<<1].sum
+tree
[u
<<1|1].sum
;}
void build(int u
,int l
,int r
)
{tree
[u
]={l
,r
,0,0};if(l
==r
) return;int mid
=l
+r
>>1;build(u
<<1,l
,mid
),build(u
<<1|1,mid
+1,r
);
}
void modify(int u
,int k
,int x
)
{if(tree
[u
].l
==tree
[u
].r
){tree
[u
].cnt
+=x
;tree
[u
].sum
+=x
*id
[k
-1];return;}int mid
=tree
[u
].l
+tree
[u
].r
>>1;if(k
<=mid
) modify(u
<<1,k
,x
);else modify(u
<<1|1,k
,x
);pushup(u
);
}
ll
query(int u
,int k
)
{if(tree
[u
].l
==tree
[u
].r
) return tree
[u
].sum
;int tmp
=tree
[u
<<1].cnt
;if(tmp
>=k
) return query(u
<<1,k
);else return tree
[u
<<1].sum
+query(u
<<1|1,k
-tmp
);
}
int main()
{IO
;cin
>>n
;build(1,1,n
);for(int i
=1;i
<=n
;i
++){cin
>>q
[i
].first
>>q
[i
].second
;id
.push_back(abs(q
[i
].second
));}sort(id
.begin(),id
.end());id
.erase(unique(id
.begin(),id
.end()),id
.end());reverse(id
.begin(),id
.end());set
<int> fire
,lightning
;int k
=0;ll res
=0;for(int i
=1;i
<=n
;i
++){if(q
[i
].first
==1){if(q
[i
].second
>0){k
++;lightning
.insert(q
[i
].second
);res
+=q
[i
].second
;modify(1,get(q
[i
].second
),1);}else{k
--;lightning
.erase(-q
[i
].second
);res
+=q
[i
].second
;modify(1,get(-q
[i
].second
),-1);}}else{if(q
[i
].second
>0){fire
.insert(q
[i
].second
);res
+=q
[i
].second
;modify(1,get(q
[i
].second
),1);}else{fire
.erase(-q
[i
].second
);res
+=q
[i
].second
;modify(1,get(-q
[i
].second
),-1);}}if(fire
.empty()){if(k
>1)cout
<<res
+query(1,k
-1)<<'\n';else cout
<<res
<<'\n';}else if(lightning
.empty()) cout
<<res
<<'\n';else{int minl
=*lightning
.begin();auto t
=fire
.end();t
--;int maxf
=*t
;if(minl
>maxf
){if(k
>1) cout
<<res
+query(1,k
-1)+maxf
<<'\n';else cout
<<res
+maxf
<<'\n';}else{if(k
>0) cout
<<res
+query(1,k
)<<'\n';else cout
<<res
<<'\n';}}}return 0;
}
要加油哦~
總結
以上是生活随笔為你收集整理的Educational Codeforces Round 93 (Rated for Div. 2)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。