C. Not Equal on a Segment
预处理找到每个位置开始的最先出现的不同的数。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int a[200010];
int diff[200010];
int main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
diff[n]=n+1;
for(int i=n-1;i>=1;i--){
if(a[i]==a[i+1]){
diff[i]=diff[i+1];
}else{
diff[i]=i+1;
}
}
while(m--){
int l,r,x;
scanf("%d%d%d",&l,&r,&x);
if(a[l]!=x){
printf("%d\n",l);
}else{
if(diff[l]<=r){
printf("%d\n",diff[l]);
}else{
printf("-1\n");
}
}
}
return 0;
}
D. Optimal Number Permutation
构造,只要相同的数距离恰当,总可以使得 s=0 。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int ans[1000010];
int main(){
int n;
cin>>n;
if(n==1){
cout<<"1 1"<<endl;
return 0;
}
if(n==2){
cout<<"1 1 2 2"<<endl;
return 0;
}
int l=1;
int r=n;
int num=1;
while(l<r){
ans[l]=ans[r]=num;
num+=2;
l++; r--;
}
l=n+1;
r=2*n-1;
num=2;
while(l<r){
ans[l]=ans[r]=num;
num+=2;
l++; r--;
}
for(int i=1;i<=n*2;i++){
if(ans[i]){
printf("%d ",ans[i]);
}else{
printf("%d ",n);
}
}
return 0;
}
E. Ants in Leaves
通过分析可以发现,不妨让深度小的叶子比深度大的先回到根,这样不会影响答案。我们依次处理根的所有子树,把该子树下的所有叶子高度找出来,排序,按高度从小到大处理。假设排序后
leaves(i)
是第
i
个叶子的高度,
#include <bits/stdc++.h>
using namespace std;
const int maxn = 500010;
vector<int> adj[maxn];
bool vis[maxn];
int depth = 0;
int ans=0;
vector<int> leaves;
void dfs(int u){
depth++;
vis[u]=1;
int sz = adj[u].size();
bool flag=1;
for(int i=0;i<sz;i++){
int v=adj[u][i];
if(vis[v])continue;
dfs(v);
flag=0;
}
if(flag){
leaves.push_back(depth);
}
depth--;
}
int main(){
int n;
cin>>n;
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
adj[u].push_back(v);
adj[v].push_back(u);
}
int sz = adj[1].size();
vis[1]=1;
for(int i=0;i<sz;i++){
int u = adj[1][i];
leaves.clear();
dfs(u);
sort(leaves.begin(),leaves.end());
int leanum = leaves.size();
int tmp=0;
for(int j=0;j<leanum;j++){
tmp=max(tmp+1,leaves[j]);
}
ans=max(ans,tmp);
}
cout<<ans<<endl;
return 0;
}
F. The Sum of the k-th Powers
看了官方题解,不得不说这题有点神。首先要知道一点,不管
k
是多少,肯定有一个最高次为
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod = 1e9+7;
ll mod_pow(ll a,ll n){
ll re=1;
while(n){
if(n&1){
re*=a;
re%=mod;
}
a*=a;
a%=mod;
n>>=1;
}
return re;
}
ll y[1000010];
void ExEuclid(ll a,ll b,ll &x,ll &y,ll &q){
if(b==0){
x=1;y=0;q=a;
return;
}
ExEuclid(b,a%b,y,x,q);
y-=x*(a/b);
}
ll inv(ll num){
ll x,y,q;
ExEuclid(num,mod,x,y,q);
if(q==1)return (x+mod)%mod;
}
int main(){
ll n,k;
cin>>n>>k;
for(int i=1;i<=k+2;i++){
y[i]=y[i-1]+mod_pow(i,k);
y[i]%=mod;
}
if(n<=k+2){
cout<<y[n]<<endl;
return 0;
}
ll dividend=1;
ll divisor=1;
for(int i = 1;i<=k+2;i++){
dividend *= (n-i);
dividend %= mod;
}
for(int i=1;i<=k+1;i++){
divisor *= i;
divisor %= mod;
}
bool minus = !(k&1);
ll ans = 0;
for(int i=1;i<=k+2;i++){
ll tmp = (dividend*inv(n-i))%mod * inv(divisor);
tmp %= mod;
tmp *= y[i];
tmp %= mod;
if(minus)tmp=-tmp;
minus = !minus;
ans += tmp;
ans += mod;
ans %= mod;
divisor*=inv(k+2-i);
divisor%=mod;
divisor*=i;
divisor%=mod;
}
cout<<ans<<endl;
return 0;
}
本文提供了几道算法竞赛题目的详细解答过程,包括不等数段查询、最优数列排列、蚂蚁路径分析及数列k次幂求和等问题。通过预处理、构造策略、图论分析及数学方法给出高效解决方案。
1317

被折叠的 条评论
为什么被折叠?



