A
思路
如果有,直接用与每个非操作一次就行,没有的话就凑两个相同的数。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
#define bl(u,i) for(int i=head[u];i;i=e[i].nxt)
#define en puts("")
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
const ll INF=0x3f3f3f3f;
void read() {}
void OP() {}
void op() {}
template <typename T, typename... T2>
inline void read(T &_, T2 &... oth)
{
int __=0;
_=0;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
__=1;
ch=getchar();
}
while(isdigit(ch))
{
_=_*10+ch-48;
ch=getchar();
}
_=__?-_:_;
read(oth...);
}
template <typename T>
void Out(T _)
{
if(_<0)
{
putchar('-');
_=-_;
}
if(_>=10)
Out(_/10);
putchar(_%10+'0');
}
template <typename T, typename... T2>
inline void OP(T _, T2... oth)
{
Out(_);
putchar('\n');
OP(oth...);
}
template <typename T, typename... T2>
inline void op(T _, T2... oth)
{
Out(_);
putchar(' ');
op(oth...);
}
/*#################################*/
const ll N=105;
ll n;
ll a[N];
void solve()
{
read(n);
ll ans=0,flag=0;
rep(i,1,n)
{
read(a[i]);
if(a[i]==0)
flag=1;
}
sort(a+1,a+n+1);
if(flag)
{
ll ans=0;
rep(i,1,n)
{
if(a[i]!=0)
++ans;
}
OP(ans);
return;
}
rep(i,1,n-1)
{
if(a[i]==a[i+1])
{
OP(n);
return;
}
}
OP(n+1);
}
int main()
{
int _;
cin>>_;
while(_--)
{
solve();
}
}
B1,B2
思路
把原串中数字每两个分为一组,如果一组中数字不同,说明需要进行一次操作变成或,要让最终连续段数目最少,就把它变成前后任意方向上第一个连续或。
代码(B2)
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
#define bl(u,i) for(int i=head[u];i;i=e[i].nxt)
#define en puts("")
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
const ll INF=0x3f3f3f3f;
void read() {}
void OP() {}
void op() {}
template <typename T, typename... T2>
inline void read(T &_, T2 &... oth)
{
int __=0;
_=0;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
__=1;
ch=getchar();
}
while(isdigit(ch))
{
_=_*10+ch-48;
ch=getchar();
}
_=__?-_:_;
read(oth...);
}
template <typename T>
void Out(T _)
{
if(_<0)
{
putchar('-');
_=-_;
}
if(_>=10)
Out(_/10);
putchar(_%10+'0');
}
template <typename T, typename... T2>
inline void OP(T _, T2... oth)
{
Out(_);
putchar('\n');
OP(oth...);
}
template <typename T, typename... T2>
inline void op(T _, T2... oth)
{
Out(_);
putchar(' ');
op(oth...);
}
/*#################################*/
void solve()
{
ll n;
string s;
read(n);
cin>>s;
s=' '+s;
ll rec=-1;
for(int i=1;i<=n;i+=2)
{
if(s[i]==s[i+1])
{
rec=i;
break;
}
}
if(rec==-1)
{
op(n/2,1);
return;
}
ll ans1=rec/2,ans2=1;
ll flag=s[rec]-'0';
for(int i=rec+2;i<=n;i+=2)
{
if(s[i]!=s[i+1])
++ans1;
else
{
if(s[i]-'0'==flag)
;
else
{
++ans2;
flag^=1;
}
}
}
op(ans1,ans2);en;
}
int main()
{
int _;
cin>>_;
while(_--)
{
solve();
}
}
C
思路
枚举,记为在第个数后面有多少比第个数小的,,确定后,答案就是,维护下数组前缀和就可以计算答案。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
#define bl(u,i) for(int i=head[u];i;i=e[i].nxt)
#define en puts("")
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
const ll INF=0x3f3f3f3f;
void read() {}
void OP() {}
void op() {}
template <typename T, typename... T2>
inline void read(T &_, T2 &... oth)
{
int __=0;
_=0;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
__=1;
ch=getchar();
}
while(isdigit(ch))
{
_=_*10+ch-48;
ch=getchar();
}
_=__?-_:_;
read(oth...);
}
template <typename T>
void Out(T _)
{
if(_<0)
{
putchar('-');
_=-_;
}
if(_>=10)
Out(_/10);
putchar(_%10+'0');
}
template <typename T, typename... T2>
inline void OP(T _, T2... oth)
{
Out(_);
putchar('\n');
OP(oth...);
}
template <typename T, typename... T2>
inline void op(T _, T2... oth)
{
Out(_);
putchar(' ');
op(oth...);
}
/*#################################*/
const ll N=5005;
ll n;
ll arr[N];
int f[N][N],s[N][N];
void print()
{
rep(i,1,n)
{
rep(j,i+1,n)
op(f[i][j]);
en;
}
}
void solve()
{
ll ans=0;
read(n);
rep(i,0,n+1)
rep(j,0,n+1)
f[i][j]=s[i][j]=0;
rep(i,1,n)
read(arr[i]);
rep(i,1,n)
{
f[i][n]=0;
for(int j=n-1;j>=i;--j)
f[i][j]=f[i][j+1]+(arr[j+1]<arr[i]);
}
rep(i,1,n)
rep(j,1,i-1)
s[i][j]=s[i][j-1]+f[j][i];
rep(a,1,n)
{
rep(c,a+2,n)
{
if(arr[c]<arr[a])
continue;
ans+=s[c][c-1]-s[c][a];
}
}
OP(ans);
}
int main()
{
int _;
cin>>_;
while(_--)
{
solve();
}
}
D
思路
对行和列分开考虑。首先考虑列,发现对于相同的,每一轮覆盖的列是相同的,所以只需要存在一个,,且还没有被覆盖过,就会贡献一次答案。
行的情况较复杂,设为到达坐标时总共覆盖的行数,那么新加入的一行是否存在,用前缀和判断一下即可。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
#define per(i,st,ed) for(int i=st;i>=ed;--i)
#define bl(u,i) for(int i=head[u];i;i=e[i].nxt)
#define en puts("")
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
const ll INF=0x3f3f3f3f;
void read() {}
void OP() {}
void op() {}
template <typename T, typename... T2>
inline void read(T &_, T2 &... oth)
{
int __=0;
_=0;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
__=1;
ch=getchar();
}
while(isdigit(ch))
{
_=_*10+ch-48;
ch=getchar();
}
_=__?-_:_;
read(oth...);
}
template <typename T>
void Out(T _)
{
if(_<0)
{
putchar('-');
_=-_;
}
if(_>=10)
Out(_/10);
putchar(_%10+'0');
}
template <typename T, typename... T2>
inline void OP(T _, T2... oth)
{
Out(_);
putchar('\n');
OP(oth...);
}
template <typename T, typename... T2>
inline void op(T _, T2... oth)
{
Out(_);
putchar(' ');
op(oth...);
}
/*#################################*/
const ll N=1e6+10;
ll n,m;
ll vis[N],ans[N],sum[N],f[N];
void solve()
{
read(n,m);
string s;
cin>>s;
s=' '+s;
ll tot=n*m,cnt=0;
rep(i,0,tot)
vis[i]=ans[i]=sum[i]=f[i]=0;
rep(i,1,tot)
{
if(!vis[i%m] && s[i]-'0')
{
vis[i%m]=1;
++cnt;
}
ans[i]=cnt;
}
rep(i,1,tot)
sum[i]=sum[i-1]+s[i]-'0';
rep(j,1,m)
{
f[j]=!!sum[j];
ans[j]+=f[j];
}
rep(i,2,n)
{
rep(j,1,m)
{
ll x=j+(i-2)*m;
f[j]=f[j]+!!(sum[x+m]-sum[x]);
ans[(i-1)*m+j]+=f[j];
}
}
rep(i,1,tot)
op(ans[i]);
en;
}
int main()
{
int _;
cin>>_;
while(_--)
{
solve();
}
}
E
思路
如果不论怎么分配贡献都是,只考虑不等的情况。发现上下对应的关系最终形成一个环(即)。对每一个环单独计算答案,一个环上的相邻节点肯定是一大一小贡献最大。
考虑一个特殊情况,就是环上最后染色的一个块,如果他前后一大一小,那么它取任意一个中间值得到的贡献总和都是一样的,所以就给他一个较靠近中间的值,防止他占用极大极小值影响其他位置贡献答案。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
#define per(i,st,ed) for(int i=st;i>=ed;--i)
#define bl(u,i) for(int i=head[u];i;i=e[i].nxt)
#define en puts("")
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
const ll INF=0x3f3f3f3f;
void read() {}
void OP() {}
void op() {}
template <typename T, typename... T2>
inline void read(T &_, T2 &... oth)
{
int __=0;
_=0;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
__=1;
ch=getchar();
}
while(isdigit(ch))
{
_=_*10+ch-48;
ch=getchar();
}
_=__?-_:_;
read(oth...);
}
template <typename T>
void Out(T _)
{
if(_<0)
{
putchar('-');
_=-_;
}
if(_>=10)
Out(_/10);
putchar(_%10+'0');
}
template <typename T, typename... T2>
inline void OP(T _, T2... oth)
{
Out(_);
putchar('\n');
OP(oth...);
}
template <typename T, typename... T2>
inline void op(T _, T2... oth)
{
Out(_);
putchar(' ');
op(oth...);
}
/*#################################*/
const ll N=1e5+10;
ll L,R,n,flag;
ll a[N],b[N],c[N],pa[N],vis[N];
void print()
{
rep(i,1,n)
op(c[a[i]]);
en;
rep(i,1,n)
op(c[b[i]]);
en;
}
void dfs(ll u)
{
vis[u]=1;
ll nxt=pa[b[u]];
if(c[b[nxt]])
{
vis[nxt]=1;
if(!flag)
c[b[u]]=--R;
return;
}
if(!flag)
c[b[u]]=--R;
else
c[b[u]]=++L;
flag^=1;
if(!vis[pa[b[u]]])
dfs(pa[b[u]]);
}
void solve()
{
read(n);
L=0,R=n+1;
rep(i,1,n)
c[i]=vis[i]=0;
rep(i,1,n)
{
read(a[i]);
pa[a[i]]=i;
}
rep(i,1,n)
{
read(b[i]);
}
rep(i,1,n)
if(!vis[i] && a[i]!=b[i])
{
flag=0;
c[a[i]]=++L;
dfs(i);
}
rep(i,1,n)
if(!c[i])
{
c[i]=++L;
}
ll ans=0;
rep(i,1,n)
ans+=abs(c[a[i]]-c[b[i]]);
OP(ans);
}
int main()
{
int _;
cin>>_;
while(_--)
{
solve();
}
}