A - Avoiding Zero
不难发现如果数组所有元素和为0一定不能满足条件,否则一定能满足。
假设所有元素和不为0尝试以下构造,如果正数和小于负数和的绝对值,那么逆序排列,否则顺序排列,这样一定满足题意。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=60;
int a[N];
int main()
{
IO;
int T=1;
cin>>T;
while(T--)
{
int n;
cin>>n;
int s=0;int s1=0,s2=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(a[i]<0) s1+=a[i];
else s2+=a[i];
s+=a[i];
}
if(s==0)
{
cout<<"NO\n";
continue;
}
sort(a+1,a+1+n);
if(-s1<s2) reverse(a+1,a+1+n);
cout<<"YES\n";
for(int i=1;i<=n;i++) cout<<a[i]<<' ';
cout<<'\n';
}
return 0;
}
B - Chess Cheater
瞎搞的
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=100010;
char s[N];
int n,k;
int main()
{
IO;
int T=1;
cin>>T;
while(T--)
{
cin>>n>>k;
cin>>s+1;
priority_queue<int,vector<int>,greater<int>> q1,q2,q3;
priority_queue<int> p1,p2;
int cnt=0;
for(int i=1;i<=n;i++)
{
if(s[i]=='L') cnt++;
else
{
if(!cnt) continue;
if(i>cnt+1&&s[i-cnt-1]=='W'&&i<=n&&s[i]=='W')
q1.push(cnt);
else if(i>cnt+1&&s[i-cnt-1]=='W'||i<=n&&s[i]=='W')
q2.push(cnt);
else
q3.push(cnt);
cnt=0;
}
}
if(cnt)
{
if(n>cnt&&s[n-cnt]=='W') q2.push(cnt);
else q3.push(cnt);
}
int res=0;
while(k&&q1.size())
{
auto v=q1.top();q1.pop();
if(k>=v) res+=2*v+1,k-=v;
else p1.push(v);
}
while(k&&q2.size())
{
auto v=q2.top();q2.pop();
if(k>=v) res+=2*v,k-=v;
else p2.push(v);
}
while(k&&(p1.size()||p2.size()))
{
res+=2*k;
k=0;
}
if(k&&q3.size())
{
auto v=q3.top();
res=2*min(k,v)-1;
}
for(int i=1;i<=n;i++)
{
if(s[i]=='W')
{
if(i>1&&s[i-1]=='W') res+=2;
else res++;
}
}
cout<<res<<'\n';
}
return 0;
}
C - The Hard Work of Paparazzi
刚开始以为是个图论题,但是有一个条件就是就算你先到了一个点你仍然要等到那个人出现的时间,也就是每个点的时间是确定的,因此每个点的时间是确定的考虑dp
状态表示:
f
i
f_i
fi表示目前在第
i
i
i个点时答案的最大值
状态转移:
f
i
=
m
a
x
(
f
i
,
f
i
+
1
)
(
∣
x
i
−
x
j
∣
+
∣
y
i
−
y
j
∣
≤
t
i
−
t
j
)
f_i=max(f_i,f_i+1)(|x_i-x_j|+|y_i-y_j|\leq t_i-t_j)
fi=max(fi,fi+1)(∣xi−xj∣+∣yi−yj∣≤ti−tj)
这样转移会发现复杂度爆炸
O
(
n
2
)
O(n^2)
O(n2),我们可以发现还有个东西一直没有用也就是地图的尺寸
r
r
r,由于
t
i
t_i
ti是顺序给出的如果当前的
t
i
−
t
j
≥
2
r
t_i-t_j\ge 2r
ti−tj≥2r不难发现
1
−
j
1-j
1−j的
f
1
−
j
f_{1-j}
f1−j都能更新
f
i
f_i
fi由此尝试维护前缀进行优化。
时间复杂度好像是
O
(
n
r
)
O(nr)
O(nr)
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=100010;
int r,n;
int f[N];
struct node
{
int x,y,t;
}a[N];
int mx[N];
int main()
{
IO;
int T=1;
//cin>>T;
while(T--)
{
cin>>r>>n;
for(int i=1;i<=n;i++) cin>>a[i].t>>a[i].x>>a[i].y;
memset(f,-0x3f,sizeof f);
memset(mx,-0x3f,sizeof mx);
a[0]={1,1,0};
f[0]=mx[0]=0;
for(int i=1;i<=n;i++)
{
for(int j=i-1;j>=0;j--)
{
if(a[i].t-a[j].t>=2*r)
{
f[i]=max(f[i],mx[j]+1);
break;
}
if(abs(a[i].x-a[j].x)+abs(a[i].y-a[j].y)<=a[i].t-a[j].t)
f[i]=max(f[i],f[j]+1);
}
mx[i]=max(mx[i-1],f[i]);
}
int res=0;
for(int i=1;i<=n;i++) res=max(res,f[i]);
cout<<res<<'\n';
}
return 0;
}
剩下的题待补
D - Unshuffling a Deck
今天早上起来想了一下这个题,想了个贪心的做法然后上课前交代码发现贪心思路不行,然后吃完午饭又想了个做法水过去了
尝试每次使得一个数排列归位。这里尝试按照
n
−
1
n
−
2
…
1
n-1\ n-2\dots \ 1%
n−1 n−2… 1的顺序
首先我们让排好序的排成(目前已经有cnt个数“归位”)这样子
{
[
n
,
n
−
1
,
n
−
2
,
.
.
.
,
n
−
c
n
t
+
1
]
[
.
.
.
n
−
c
n
t
]
[
.
.
.
.
]
}
\{[n,n-1,n-2,...,n-cnt+1][...n-cnt][....]\}
{[n,n−1,n−2,...,n−cnt+1][...n−cnt][....]}我们只需要这样划分就可以在此归位一个数
{
[
1
]
.
.
.
[
1
]
[
1
]
⏟
c
n
t
[
l
e
n
1
]
[
l
e
n
2
]
}
\{ \underbrace{[1]...[1][1]}_{cnt}[len_1][len_2]\}
{cnt
[1]...[1][1][len1][len2]}
这样操作后原序列即变成
{
[
.
.
.
.
.
.
]
[
n
−
c
n
t
,
n
−
c
n
t
+
1
,
.
.
.
,
n
]
}
\{[......][n-cnt,n-cnt+1,...,n]\}
{[......][n−cnt,n−cnt+1,...,n]}
然后如法炮制的操作,一共进行n次即可归位。还有些细节可以看代码
细节1:n奇偶性,最后一次操不能让序列变成全部逆序的情况,需要顺序
细节2:划分需要至少划分2个断,最后需要把划分成1个段(无效操作)清除掉。
上述方法一定能在n次操作以内完成序列顺序。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=60;
int n,cnt;
int a[N],b[N];
vector<int> ans[N];
int main()
{
IO;
int T=1;
//cin>>T;
while(T--)
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
bool flag;
int now=n;
if(n&1) flag=0;
else flag=1;
for(int k=1;k<=n;k++)
{
int p;
for(int i=1;i<=n;i++)
if(a[i]==now) p=i;
//cout<<p<<':';
//cout<<(int)flag<<'\n';
if(!flag)// 左边整齐
{
for(int i=1;i<=cnt;i++) ans[k].push_back(1);
if(p-cnt) ans[k].push_back(p-cnt);
if(n-p) ans[k].push_back(n-p);
for(int i=p+1,j=1;i<=n;i++,j++) b[j]=a[i];// p+1~n -> 1~n-p n-p
for(int i=cnt+1,j=n-p+1;i<=p;i++,j++) b[j]=a[i];// cnt+1~p -> n-p+1 p-cnt
for(int i=1,j=n;i<=cnt;i++,j--) b[j]=a[i];// 1~cnt -> n~n-cnt+1 cnt
for(int i=1;i<=n;i++) a[i]=b[i];
}
else
{
if(p-1>0) ans[k].push_back(p-1);
if(n-cnt-p+1>0) ans[k].push_back(n-cnt-p+1);
for(int i=1;i<=cnt;i++) ans[k].push_back(1);
for(int i=1,j=n-p+2;i<=p-1;i++,j++) b[j]=a[i];
for(int i=p,j=cnt+1;i<=n-cnt;i++,j++) b[j]=a[i];
for(int i=n-cnt+1,j=cnt;i<=n;i++,j--) b[j]=a[i];
for(int i=1;i<=n;i++) a[i]=b[i];
}
now--;
cnt++;
flag^=1;
}
int res=0;
for(int i=1;i<=n;i++)
if(ans[i].size()>1) res++;
cout<<res<<'\n';
for(int i=1;i<=n;i++)
{
if(ans[i].size()>1)
{
cout<<ans[i].size()<<' ';
for(auto t:ans[i]) cout<<t<<' ';
cout<<'\n';
}
}
}
return 0;
}
E - Xum
要加哟哦~