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);
}
}

浙公网安备 33010602011771号