Codeforces Round #788 (Div. 2) A B C D E
打的好 ** 烂总结一下把。
A.Prof. Slim
解法: 贪心,统计正负符号,因为每个位上的数只能是其绝对值的正负形式,所以让所有负号出现在左边,正号出现在右边。 此时已经是最优形式,如果还是出现后一项小于前一项那么答案是NO。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e5+10;
int a[N];
void cf(){
int n;
cin>>n;
int res1,res2;
res1=res2=0;
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]<0)res1++;
else res2++;
}
for(int i=1;i<=n;i++){
if(i<=res1)a[i]=abs(a[i])*-1;
else a[i]=abs(a[i]);
}
for(int i=2;i<=n;i++){
if(a[i]<a[i-1]){
cout<<"NO"<<endl;
return ;
}
}
cout<<"YES"<<endl;
return ;
}
signed main(){
int t=1;
cin>>t;
while(t--){
cf();
}
}
B.Dorms War
解法: 给B薄纱了,赛后发现其实真的很简单。正解是统计最长的两个特殊字符之间的距离。 原因:如果产生最长的距离的两个字符
a
a
a和
b
b
b出现在中间,那么后一个字符会被后面距离较短字符
a
1
a1
a1和
b
1
b1
b1中的
b
1
b1
b1所吸收,使得
b
1
b1
b1取代
b
b
b的地位,但本质实则是不变的,也就是
b
1
b1
b1到
a
a
a的次数和
b
b
b到
a
a
a的次数是一样的。其前面的距离较短字符
a
2
a2
a2和
b
2
b2
b2也一定会在
b
b
b到
a
a
a的过程中完全消失。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
set<char>ss;
const int N = 2e5+10;
int sum[N];
void cf(){
int n;
cin>>n;
for(int i=0;i<=n;i++)sum[i]=0;
string s;
cin>>s;
string end;
ss.clear();
int m;
cin>>m;
for(int i=1;i<=m;i++){
char sss;
cin>>sss;
ss.insert(sss);
}
int last=0;
int ma=0;
for(int i=0;i<s.size();i++){
if(ss.count(s[i])){
ma=max(ma,i-last);
last=i;
}
}
cout<<ma<<endl;
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int t=1;
cin>>t;
while(t--){
cf();
}
}
C.Where is the Pizza?
思路: 首先考虑该题如果没有
d
d
d数组限制会如何,那么我们需要考虑的就是
a
a
a和
b
b
b数组构造排列的方案数。仔细观察容易发现数组
a
a
a和数组
b
b
b中的数是可以构成环的,在这个环中出现的数必定出现
2
2
2次,例如数据: 1 5 2 4 6 3 6 5 3 1 4 2
1 6 4 1 便是一个环,在没有d数组约数情况下,显然该处可产生两组数据,1 4 6 和 6 1 4 那么对于总方案数的贡献就是
?
*
?
2
2
2,但是如果d数组有约束,即
a
[
i
]
=
b
[
i
]
a[i]=b[i]
a[i]=b[i],那么
d
[
i
]
d[i]
d[i]必然是固定的,或者输入就已给出的情况,那么整个环的方案即唯一,那么对总方案数的贡献就是
?
*
?
1
1
1,那么我们要做的就是暴力判环,以及判段时候
d
d
d数组存在约束,最终快速幂或者累乘都可。此处的暴力判环我实现的方法是数组映射。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e5+10;
int a[N],b[N],c[N];
int ba[N];
bool ok[N];
bool st;
int sta;
const int mod=1e9+7;
void cf(){
int n;
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i],ok[i]=false;
for(int i=1;i<=n;i++)cin>>b[i];
for(int i=1;i<=n;i++)cin>>c[i];
int ti=0;
for(int i=1;i<=n;i++){
ba[a[i]]=i;
}
int ans=1;
for(int i=1;i<=n;i++){
if(!ok[i]){
st=true;
if(a[i]==b[i]||c[i])st=false;
ok[i]=true;
int j;
j=ba[b[i]];
while(1){
if(j==i)break;
if(a[j]==b[j]||c[j])st=false;
ok[j]=true;
j=ba[b[j]];
}
if(st)ans=ans*2%mod;
}
}
cout<<ans<<endl;
}
signed main(){
int t=1;
cin>>t;
while(t--){
cf();
}
}
D.Very Suspicious
思路: 找规律+递归+二分。先偷个图会更容易理解。 在草稿纸上画图,枚举前几条线最多能带来多少个等边三角形。发现规律,每画一条固定斜率的一条线,会产生
2
?
(
和
其
斜
率
不
相
同
直
线
个
数
)
2*(和其斜率不相同直线个数)
2?(和其斜率不相同直线个数)个等边三角形。又因为一共只有
3
3
3条不同斜率的线可画,那么最贪心方法就是 0 0 0 = 0,1 0 0 = 0,1 1 0 = 2,1 1 1 = 4 ,2 1 1 = 4, 2 2 1 = 6 ,2 2 2 =8… 然后我是暴力map存下能实现不超过
1
e
9
1e9
1e9个等边三角形的直线个数,然后二分查找。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
map<int,int>mp;
int ed;
void init(){
int all=1e9;
int st=1;
int number=0;
int sum=0;
for(int i=1;;i++){
if(sum>=all)break;
if(st%3!=1){
number+=2;
}
sum+=number;
mp[i]=sum;
st++;
ed=i;
}
}
void cf(){
int l=1,r=ed;
int n;
cin>>n;
while(l<r){
int mid=l+r>>1;
if(mp[mid]>=n)r=mid;
else l=mid+1;
}
cout<<l<<endl;
return ;
}
signed main(){
init();
int t=1;
cin>>t;
while(t--){
cf();
}
}
E.Hemose on the Tree
思路: 最小的最大路径异或答案必然大于等于
2
p
2^p
2p,因为假设我们根结点的赋值为小于等于
2
p
2^p
2p的值,因为存在
2
p
+
1
2^p+1
2p+1 ~
2
p
+
2
p
?
1
2^p+2^p-1
2p+2p?1之间的数,我们必然会产生高位。所以路径异或答案必然大于等于
2
p
2^p
2p。接下去进行构造,因为结点个数比边数多
1
1
1,所以我们只要让结点
1
1
1赋值为
2
p
2^p
2p,剩下的每一条边及链接的结点只需按照如下形式构造即可。如果前面路径异或答案为
x
(
x
<
2
p
)
x(x<2^p)
x(x<2p),那么我当前值构造为
x
+
2
p
x+2^p
x+2p,如果前面路径异或答案为
x
(
x
>
=
2
p
)
x(x>=2^p)
x(x>=2p),我们将当前值构造为
x
+
1
x+1
x+1即可目的为了消去高位。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int,int>PII;
const int N = 3e5+10;
vector<PII>v[N];
int dp1[N],dp2[N];
int st;
int n;
void dfs(int u,int fa,int g){
for(auto x:v[u]){
if(x.first==fa)continue;
st++;
dp1[x.first]=st^g;
dp2[x.second]=st^g^n;
dfs(x.first,u,g^n);
}
}
void cf(){
cin>>n;
n=1<<n;
st=0;
for(int i=1;i<=n;i++){
v[i].clear();
dp1[i]=dp2[i]=0;
}
for(int i=1;i<=n-1;i++){
int a,b;
cin>>a>>b;
v[a].push_back({b,i});
v[b].push_back({a,i});
}
dp1[1]=n;
cout<<1<<endl;
dfs(1,-1,0);
for(int i=1;i<=n;i++)cout<<dp1[i]<<' ';
cout<<endl;
for(int i=1;i<=n-1;i++)cout<<dp2[i]<<' ';
cout<<endl;
return ;
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int t=1;
cin>>t;
while(t--){
cf();
}
}
|