abc_467训练记录
C
注意到一个位置要么操作,要么不操作,这是一个经典的 dp 题。
设 \(dp_{i,0/1}\) 表示当前考虑当第 \(i\) 个位置,且当前位置不修改/修改的最小所需花费。
可以将 \(a_i,b_i\) 都看做 bool 变量
转移方程如下:
- \(dp_{i,0}=min(dp_{i-1,0}[(a_i+a_{i-1})\mod 2=b_{i-1}],dp_{i-1,1}[(a_i+a_{i-1}\oplus 1)\mod 2=b_{i-1}])\)
- \(dp_{i,1}=min(1+dp_{i-1,1}[(a_i\oplus 1+a_{i-1})\mod 2=b_{i-1}],1+dp_{i-1,1}[(a_i\oplus 1+a_{i-1}\oplus 1)\mod 2=b_{i-1}])\)
答案取 \(min(dp_{n,0},dp_{n,1})\)
时间复杂度为\(O(n)\)
D
设第一个圆上的两个点为\(A,B\),第二个圆上的两个点为\(C,D\)
不难发现:圆心必定交与\(AB\)和\(CD\)的垂直平分线上。
若\(AB\)与\(CD\)不平行,则一定存在这样的圆心,且唯一存在;
否则,若\(AB\)与\(CD\)是平行的,那么如果存在这样的圆心,一定要求两条垂直平分线是重合的,满足这样的条件则要\(ABDC\)是等腰梯形。
可以用点积判断两个向量是否平行。
若\(ABDE\)是等腰梯形,则要求\(\ang CAB=\ang ABD\),则\(\vec{AB}\cdot \vec{AC}=\vec{BA}\cdot\vec{BD}\)
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<cmath>
#include<bitset>
#include<cstring>
#include<queue>
#include<iomanip>
#define mt make_tuple
//cout << setprecision(3) ; //输出3位小数,3.142
#define pb push_back
#define fi first
#define se second
using namespace std;
using ll=long long;
typedef pair<int,int>pii;
typedef tuple<int,int,int>ti3;
const int N=3e5+10;
const double eps=1e-9;
const double pi=acos(-1.0);
int sgn(double x){
if(fabs(x)<eps)return 0;
if(x<eps)return -1;
return 1;
}
int dcmp(double x,double y){
return sgn(x-y);
}
template<class T>
class Point{
public:
T x,y;
Point():x(0),y(0){}
Point(T x,T y):x(x),y(y){}
Point operator +(const Point B){
return Point(x+B.x,y+B.y);
}
Point operator -(const Point B){
return Point(x-B.x,y-B.y);
}
bool operator==(const Point&a){
return x-a.x==0&&y-a.y==0;
}
T operator*(const Point&a) const{//dot
return this->x*a.x+this->y*a.y;
}
T operator^(const Point&a){//cross
return this->x*a.y-a.x*this->y;
}
T len2(){
return (*this)*(*this);
}
void in(){
cin>>x>>y;
}
};
void Silverwolf(){
Point<ll>p1,p2,p3,p4;
p1.in();
p2.in();
p3.in();
p4.in();
if((p1==p3)&&p2==p4)cout<<"Yes\n";
else if(p1==p4&&p2==p3)cout<<"Yes\n";
else{
Point<ll>v21=p2-p1;
Point<ll>v43=p4-p3;
Point<ll>v31=p3-p1;
Point<ll>v42=p4-p2;
if((v21^v43)==0){
//平行
//梯形
if(v21*v31+v21*v42==0){
cout<<"Yes\n";
}else cout<<"No\n";
}else cout<<"Yes\n";
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;cin>>T;while(T--)
Silverwolf();
//愿艾利欧三度为你窥见,令你的生命永不停歇,骇入永远成功,游戏永远胜利。
//游戏就只是为了游戏,仅此而已
//acm这种东西,三两下搞定就好啦
return 0;
}
E
如果固定第一个位置,则对于 \([2,n]\) 的所有位置, 它的贡献都被固定了,且固定为 \(c_i\)
不妨考虑每次增加第一个位置,发现对于偶数位,它的贡献是在模意义下 -1 ,对于奇数位,它的贡献是在模意义下 +1。这时,我们得到的东西时间复杂度是\(O(nm)\)的。
不妨先只考虑偶数位,它的贡献在枚举第一个位置为 \(c_i+1\) 时刻会跃变。在\([1,c_i]\) 时刻,其贡献等价于每一次都是 -1,在 \([c_i+1,m)\) 时刻,它的贡献会在此时刻从 \(m-1\) 开始继续往下 -1 。我们可以假设对于所有位置,在 \(t\) 时刻,贡献全部是 \(-t\) 的,而在贡献跃变时刻,将贡献改成$ m-1+c_i+1$ 开始继续维护需要降低的贡献,可以用优先队列维护当前最快要跃迁的位置。
那奇数位呢?同理,它的贡献会在 \(T=m-c_i\) 时刻跃变,在\([1,T]\)时刻,每次贡献都是要 \(+1\)。在\([1,T]\)时刻,其贡献每次都会要+1,在\([T+1,m)\)时刻,它的贡献会从此最早时刻从\(-T\)开始向上涨。
这样如果枚举所有时刻,那么已经可以用优先队列快速维护贡献,每个位置至多被出队一次。
你发现,对于两个时刻\([t_1,t_2]\)之间,每次都会上涨或下降相同的贡献,因此,我的贡献最优值一定会在端点处取到,所以我改成枚举所有端点值。
综上,时间复杂度为\(O(n\log n)\)。
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<cmath>
#include<bitset>
#include<cstring>
#include<queue>
#include<iomanip>
#define mt make_tuple
//cout << setprecision(3) ; //输出3位小数,3.142
#define pb push_back
#define fi first
#define se second
using namespace std;
using ll=long long;
typedef pair<int,int>pii;
typedef tuple<int,int,int>ti3;
const int N=3e5+10;
//bi=0 or 1
const int inf=1e9+7;
void Silverwolf(){
int n,m;
cin>>n>>m;
vector<int>a(n+1,0),b(n,0),c(n+1,0);
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<n;i++)cin>>b[i];
//固定 a[1]
//对于 [2,n] 的所有位置 计算一下需要修改的位置有多少个
auto mo=[&](int x){
return (x%m+m)%m;
};
for(int i=2;i<=n;i++){
c[i]=mo(b[i-1]-a[i-1]-a[i]);
a[i]=mo(b[i-1]-a[i-1]);
}
ll ans=0;
for(int i=2;i<=n;i++)ans+=c[i];
ll sum=0,cnt1=0,cnt2=0;
vector<int>times;//枚举时间
priority_queue<int,vector<int>,greater<int>>que;// 小根
priority_queue<int>que2;//大根
auto add=[&](int x)->void{
if(x>=0&&x<m)times.pb(x);
};
for(int i=2;i<=n;i++){
if(i%2==0){
add(c[i]);
add(c[i]+1);
add(c[i]-1);
que.push(c[i]);
sum+=c[i];
cnt1++;
}
else{
add(m-c[i]);
add(m-c[i]-1);
add(m-c[i]+1);
que2.push(c[i]);
sum+=c[i];
cnt2++;
}
}
sort(times.begin(),times.end());
times.erase(unique(times.begin(),times.end()),times.end());
sort(times.begin(),times.end());
int lt=0;
for(auto t:times){
while(que.size()&&que.top()==t-1){
auto tmp=que.top();
sum-=tmp;
que.pop();
tmp=m-1+t;
sum+=tmp;
que.push(tmp);
}
while(que2.size()&&que2.top()+t==m){
auto tmp=que2.top();
que2.pop();
sum-=tmp;
tmp=-t;
sum+=tmp;
que2.push(tmp);
}
ans=min(ans,t+sum-t*cnt1+t*cnt2);
}
cout<<ans<<'\n';
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
// int T;cin>>T;while(T--)
Silverwolf();
//愿艾利欧三度为你窥见,令你的生命永不停歇,骇入永远成功,游戏永远胜利。
//游戏就只是为了游戏,仅此而已
//acm这种东西,三两下搞定就好啦
return 0;
}
浙公网安备 33010602011771号