Codeforces Round 997 (Div. 2)

A. Shape Perimeter

根据小学知识,可以拉成矩形

B. Find the Permutation

u->v有边,说明在排列中u<v,uv的位置是正序

遍历所有u<v
有边,v前面的数有u
无边,u一定在v后面

可以加完所有偏序关系之后topo序
但由于两两都有偏序关系,可以直接计数排序
遍历所有u<v
有边,v前面的数有u idx[v]++
无边,u一定在v后面 idx[u]++

#include<iostream>
using namespace std;
#include<cstring>

const int N=1010;
int n;
int idx[N];
int a[N];

int main(){
int T;cin>>T;
while(T--){
    cin>>n;
    memset(idx,0,sizeof(idx));
    for(int i=1;i<=n;i++){
            string str;
        cin>>str;
        for(int j=i+1;j<=n;j++){
            int t =(str[j-1]=='1')?1:0;
            if(t){
                idx[j]++;
            }else {
            idx[i]++;
            }
        }
    }
    for(int i=1;i<=n;i++){

        a[idx[i]+1]=i;
    }
    for(int i=1;i<=n;i++){
        printf("%d ",a[i]);
    }printf("\n");
}

}

C. Palindromic Subsequences

其中一种构造方法是:
奇数 2 3 4 1 2 3 4 3+3+3
2 3 4 5 1 2 3 4 5 4+4+4+4
偶数 2 3 4 5 2 3 4 5 3+3+3+3
2 3 4 5 6 2 3 4 5 6 4+4+4+4+4
可以看到增长很快,n>=7均是成立的
而n==6题目给出来了

#include<iostream>
using namespace std;

int n;

int main(){

int T;cin>>T;
while(T--){
    cin>>n;
    if(n==6){
            printf("1 1 2 3 1 2\n");
        continue;
    }
    int idx=1;
    for(int i=1;i<=n/2;i++){
        printf("%d ",++idx);
    }
    if(n&1)printf("1 ");
    idx=1;
    for(int i=(n+1)/2+1;i<=n;i++){
        printf("%d ",++idx);
    }
    printf("\n");
}

}

D. Unique Median

反过来,不好子数组两个中位数不等,说明有那么一个数
1 2 3 3 4|5 5 6 7 9
<=4的和>4的相等

枚举中位数x,
<=x的设为-1,>x的设为1,不好子数组就是数组和为0

和为0的子数组个数,即s[r]==s[l-1]的个数
for(ll i=1;i<=n;i++){
mp[s[i-1]]++;
res+=mp[s[i]];
}

为了避免像
1 2 3 3 3|5 5 6 7 9这种对3算了一遍,对4算了一遍
确保有x
如果有x,才可以把左端点[上一个x后,这一个x]的都加上
顺便看一下,l由上一个x后变到了这一个x后

for(ll l=1,r=1;r<=n;r++){
    if(a[r]==x){
        for(;l<=r;l++)mp[s[l-1]]++;
    }
    res+=mp[s[r]];
}


#include<iostream>
using namespace std;
#include<map>
#define ll long long
const ll N=100010;
ll a[N];ll b[N];ll s[N];
ll n;
map<ll,ll> mp;

ll work(ll x){
ll res=0;mp.clear();
for(ll i=1;i<=n;i++){
    if(a[i]<=x)b[i]=-1;
    else b[i]=1;
}

s[0]=0;
for(ll i=1;i<=n;i++){
s[i]=s[i-1]+b[i];
}


//s[r]-s[l-1]==0的个数

/*
for(ll i=1;i<=n;i++){
        mp[s[i-1]]++;
    res+=mp[s[i]];
}*/

for(ll l=1,r=1;r<=n;r++){
    if(a[r]==x){
        for(;l<=r;l++)mp[s[l-1]]++;
    }
    res+=mp[s[r]];
}


return res;
}


int main(){
ll T;cin>>T;
while(T--){
    cin>>n;
    for(ll i=1;i<=n;i++)scanf("%lld",&a[i]);

    ll ans=n*(n+1)/2;
    for(ll i=1;i<=10;i++){
        ans-=work(i);
    }
    printf("%lld\n",ans);
}

}

posted @ 2025-07-03 22:20  arin876  阅读(15)  评论(0)    收藏  举报