今天是 ABC429 CDEF。被 E 卡到破防说是。代码能力场。
ABC429C
给三元组的样子分个类,\(AAB,ABB,ABA\) 这三种。
对于前两种,用个桶前缀后缀一下算贡献即可。
对于中间的,我们动态维护每种数左边和右边数量的乘积,因为每次只会改一个数,维护是简单的。
剩下就是代码了,一遍写对。
code
Show me the code
#define rd read()
#define mkp make_pair
#define ls p<<1
#define rs p<<1|1
#define rep(i,a,b) for( int i=(a); i<=(b); ++i)
#define per(i,a,b) for( int i=(a); i>=(b); --i)
#include<bits/stdc++.h>
using namespace std;
typedef long long i64;
typedef unsigned long long u64;
typedef unsigned int u32;
typedef __int128 i128;
i64 read(){i64 x=0,f=1;char c=getchar();while(c>'9'||c<'0'){if(c=='-') f=-1;c=getchar();}while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}return x*f;
}
const int N=2e5+5;
i64 a[N];
i64 t[N];
i64 t1[N];
i64 t2[N];
pair<i64,i64> t3[N];
int main(){int n;cin>>n;for(int i=1;i<=n;i++){cin>>a[i];t[a[i]]++;}i64 ans=0;for(int i=1;i<=n;i++){t1[a[i]]++;if(t1[a[i]]>=2){ans+=(t1[a[i]]-1)*(n-i-(t[a[i]]-t1[a[i]]));}t3[i].second=t[i];}for(int i=n;i>=1;i--){t2[a[i]]++;if(t2[a[i]]>=2){ans+=(t2[a[i]]-1)*(i-1-(t[a[i]]-t2[a[i]]));}}i64 msum=0;for(int i=1;i<=n;i++){msum-=t3[a[i]].first*t3[a[i]].second;ans+=msum;t3[a[i]].first++;t3[a[i]].second--;msum+=t3[a[i]].first*t3[a[i]].second;}cout<<ans;return 0;
}
ABC429D
朴素二分题,首先离散化,把每个放了人的位置的答案计算出来即可。
注意环的处理和相邻人的位置贡献的计算。
赛时好像这题也卡飞不少人?
code
Show me the code
#define rd read()
#define mkp make_pair
#define ls p<<1
#define rs p<<1|1
#define rep(i,a,b) for( int i=(a); i<=(b); ++i)
#define per(i,a,b) for( int i=(a); i>=(b); --i)
#include<bits/stdc++.h>
using namespace std;
typedef long long i64;
typedef unsigned long long u64;
typedef unsigned int u32;
typedef __int128 i128;
i64 read(){i64 x=0,f=1;char c=getchar();while(c>'9'||c<'0'){if(c=='-') f=-1;c=getchar();}while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}return x*f;
}
const int N=2e5+5;
i64 a[N];
i64 t[N];
i64 t1[N];
i64 t2[N];
pair<i64,i64> t3[N];
int main(){int n;cin>>n;for(int i=1;i<=n;i++){cin>>a[i];t[a[i]]++;}i64 ans=0;for(int i=1;i<=n;i++){t1[a[i]]++;if(t1[a[i]]>=2){ans+=(t1[a[i]]-1)*(n-i-(t[a[i]]-t1[a[i]]));}t3[i].second=t[i];}for(int i=n;i>=1;i--){t2[a[i]]++;if(t2[a[i]]>=2){ans+=(t2[a[i]]-1)*(i-1-(t[a[i]]-t2[a[i]]));}}i64 msum=0;for(int i=1;i<=n;i++){msum-=t3[a[i]].first*t3[a[i]].second;ans+=msum;t3[a[i]].first++;t3[a[i]].second--;msum+=t3[a[i]].first*t3[a[i]].second;}cout<<ans;return 0;
}
ABC429E
真正的红如温。后 50min 全是这个题。
你说得对但是 5min 想懂了再 5min 就写完了。但是它就是不过啊。
普通 BFS 题,每个 S 算贡献即可。用 BFS 处理出每个点到一个 S 的最短路和不同 S 的非严格次短路。
但就是这种东西我也能写挂把。
赛后又写了一遍就过了,我咋看不出这两种写法的区别呢?
code
Show me the code
#define rd read()
#define mkp make_pair
#define ls p<<1
#define rs p<<1|1
#define rep(i,a,b) for( int i=(a); i<=(b); ++i)
#define per(i,a,b) for( int i=(a); i>=(b); --i)
#include<bits/stdc++.h>
using namespace std;
typedef long long i64;
typedef unsigned long long u64;
typedef unsigned int u32;
typedef __int128 i128;
i64 read(){i64 x=0,f=1;char c=getchar();while(c>'9'||c<'0'){if(c=='-') f=-1;c=getchar();}while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}return x*f;
}
const int N=3e5;
vector<int> e[N];
int d1[N],d2[N];
int f1[N],f2[N];
struct work{int v;int w;int id;
};
queue<work> q;
int main(){int n;cin>>n;int m;cin>>m;for(int i=1;i<=m;i++){int u,v;cin>>u>>v;e[u].push_back(v);e[v].push_back(u);}string s;cin>>s;s=' '+s;memset(d1,0x3f,sizeof d1);memset(d2,0x3f,sizeof d2);for(int i=1;i<=n;i++){if(s[i]=='S'){q.push(work{i,0,i});f1[i]=i;d1[i]=0;}}while(q.size()){int u=q.front().v;int w=q.front().w;int id=q.front().id;q.pop();w++;for(int v:e[u]){if(d1[v]==0x3f3f3f3f){d2[v]=d1[v];d1[v]=w;f1[v]=f2[v];f1[v]=id;}else if(d2[v]==0x3f3f3f3f&&f1[v]!=id){d2[v]=w;f2[v]=id;}else continue;q.push(work{v,w,id});}}for(int i=1;i<=n;i++){if(s[i]=='D'){cout<<d1[i]+d2[i]<<'\n';}}return 0;
}
ABC429F
线段树题,写不完了晚上回来再写。