https://atcoder.jp/contests/abc385
C:
没有什么很巧的办法,只能暴力,虽然3000的n也不是很小,但是大胆暴力即可。。
遍历所有间隔len;对每个间隔遍历起始点;遍历这个间隔上的所有点;
虽然写了个三重循环,但是仔细看一下复杂度时n方的。
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
using ll = long long;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
void solve(){
int n;
cin>>n;
vector<int> H(n+1);
for(int i=1;i<=n;i++) cin>>H[i];
int ans = 1;
for(int len = 1;len<n;len++){
for(int st = 1;st<=len;st++){
int cnt = 1;
for(int i = st+len;i<=n;i+=len){
if(H[i] == H[i-len]){
cnt++;
ans = max(ans,cnt);
}else{
cnt = 1;
ans = max(ans,cnt);
}
}
}
}
cout<<ans<<endl;
}
int main(){
ifstream test_file("0in.txt");
if (test_file) {
freopen("0in.txt", "r", stdin);
freopen("0output.txt", "w", stdout);
}
std::ios::sync_with_stdio(0);std::cout.tie(0);std::cin.tie(0);
int T = 1;
#ifdef MULTI_TEST
cin>>T;
#endif
while(T--){
solve();
}
return 0;
}
D:
感觉是大模拟,非常的没有意思
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
using ll = long long;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
void solve(){
ll n,m;
ll sx,sy;
cin>>n>>m>>sx>>sy;
vector<pair<char,ll>> path;
//vector<pair<ll,ll>> point(n+1);
set<pll> S1,S2;
for(int i=1;i<=n;i++){
//cin>>point[i].first>>point[i].second;
ll x,y; cin>>x>>y;
S1.insert({x,y});
S2.insert({y,x});
}
for(int i=0;i<m;i++){
char c;
ll x;
cin>>c>>x;
path.push_back({c,x});
}
//sort(point.begin()+1,point.end());
ll ans = 0;
ll x = sx,y = sy;
for(auto [c,d]:path){
ll nx,ny;
if(c=='U'){
nx = x,ny = y+d;
}else if(c=='D'){
nx = x,ny = y-d;
}else if(c=='L'){
nx = x-d,ny = y;
}else if(c=='R'){
nx = x+d,ny = y;
}
if(c=='U'||c=='D'){
ll st = min(y,ny),ed = max(y,ny);
auto idx = S1.lower_bound({x,st});
while(idx!=S1.end()&&idx->first == x&&idx->second>=st&&idx->second<=ed){
ans++;
idx++;
auto [a,b] = *prev(idx);
S1.erase(prev(idx));
S2.erase({b,a});
}
}else{
ll st = min(x,nx),ed = max(x,nx);
auto idx = S2.lower_bound({y,st});
while(idx!=S2.end()&idx->first == y&&idx->second>=st&&idx->second<=ed){
ans++;
idx++;
auto [a,b] = *prev(idx);
S2.erase(prev(idx));
S1.erase({b,a});
}
}
x = nx,y = ny;
}
cout<<x<<" "<<y<<" "<<ans<<endl;
}
int main(){
ifstream test_file("0in.txt");
if (test_file) {
freopen("0in.txt", "r", stdin);
freopen("0output.txt", "w", stdout);
}
std::ios::sync_with_stdio(0);std::cout.tie(0);std::cin.tie(0);
int T = 1;
#ifdef MULTI_TEST
cin>>T;
#endif
while(T--){
solve();
}
return 0;
}
E:
纠结在老觉得这题有什么巧妙的trick,,,其实直接枚举每个点作为中心点是可以做的。
那中心点确定后,怎么快速计算出最少删掉多少个点呢?这里还要想到一个很基础的点:如果x,y确定,那么要删去的点就是$N-(1+x+x*y)$,所以需要找到对于这个中心点合法的x,y,并让他们尽量大即可。考虑第一层的所有点$u_i$,对每个点,能达到的最大y就是他们的度再减一。所以假设y固定,则x最大就是第一层的点,满足度数大于y的个数。
所以对每一个点,遍历一下以该点为根,深度为1的所有点即可。这个是O(n)的。又由于按度数排序遍历,所以复杂度O(nlogn)
int n;
vector<vector<int>> g;
void solve(){
cin>>n;
vector<int> d(n+1);
g.resize(n+1);
for(int i=0;i<n-1;i++){
int u,v; cin>>u>>v;
g[u].emplace_back(v);
g[v].emplace_back(u);
d[u]++,d[v]++;
}
int ans = n;
for(int i=1;i<=n;i++){
vector<int> node = g[i];
sort(node.begin(),node.end(),[&](int a,int b){
return d[a]>d[b];
});
int x = 0,y = 0;
for(auto v:node){
x++;
y = d[v] - 1;
ans = min(ans,n - (1+x+x*y));
}
}
cout<<ans<<endl;
}
F:
难蚌。需要发现答案就是所有不被前一个建筑遮挡的h的最大值即可。
然后要开long double,不然精度被卡
void solve(){
int n;
cin>>n;
vector<pdd> point(n+1);
for(int i=1;i<=n;i++){
cin>>point[i].first>>point[i].second;
}
long double ans = -1;
for(int i=1;i<n;i++){
auto [x1,h1] = point[i];
auto [x2,h2] = point[i+1];
ans = max(ans,(h2*x1 - h1*x2)/(x1-x2));
}
if(ans<0) cout<<"-1"<<endl;
else cout<<fixed<<setprecision(10)<<ans<<endl;
}