【Codeforces Round #665 (Div. 2)】2020/8/21 晚上打完球就22:10了,愣是没报上名(cf打不开,然后就做了一下赛后交的过了3个题
A - Distance and Axis
数学题分类讨论一下即可
#define IO ios::sync_with_stdio(false);
cin.tie();
cout.tie(0)
#pragma GCC optimize(2)
#include
#include
using namespace std;
int n,k;
int main()
{
IO;
int T;
cin>>T;
while(T--)
{
cin>>n>>k;
int res=0;
if(k>n)
{
res+=k-n;
}
else
{
if(k%2!=n%2) res++;
}
cout<
B - Ternary Sequence
贪心,先让第一个序列的2找第二个序列的1配对(加分), 然后看看第一个序列的1先找第二个序列的0和1配对(分数不变),最后找第二个序列2配对(减分)
#define IO ios::sync_with_stdio(false);
cin.tie();
cout.tie(0)
#pragma GCC optimize(2)
#include
#include
using namespace std;
typedef long long ll;
typedef pair pii;
ll x,y,z;
ll a,b,c;
int main()
{
IO;
int T;
cin>>T;
while(T--)
{
cin>>x>>y>>z;
cin>>a>>b>>c;
ll res=0;
res+=2*min(z,b);
y-=a;
y-=b-min(z,b);
if(y>0) res-=2*y;
cout<
C - Mere Array
这题是个脑筋急转弯。首先先找到数组中最小的数
mina
如果想要交换两个数,那么两个数的最大公因数必须是mina
,然后可以先把原数组排序不妨记作数组b[]
,如果a[i]!=b[i]
说明原数组中该位置的值需要交换位置,那么这个数必须是mina
的倍数,并且只要是这个数的倍数就一定能交换(我们可以考虑让它和mina所在位置交换)。因此只要位置不正确的数全都是mina
的倍数就可以满足题意。#define IO ios::sync_with_stdio(false);
cin.tie();
cout.tie(0)
#pragma GCC optimize(2)
#include
#include
using namespace std;
typedef long long ll;
typedef pair pii;
const int N=200010;
int a[N],b[N];
int n;
int main()
{
IO;
int T;
cin>>T;
while(T--)
{
cin>>n;
int mina=1e9+1;
for(int i=1;
i<=n;
i++)
{
cin>>a[i];
b[i]=a[i];
mina=min(mina,a[i]);
}
sort(b+1,b+1+n);
bool ok=1;
for(int i=1;
i<=n;
i++)
if(a[i]!=b[i]&&a[i]%mina!=0)
{
ok=0;
break;
}
if(ok) cout<<"YES"<
D - Maximum Distributed Tree
贪心:可以考虑统计每条边通过的次数,然后通过次数多的分配边权最大。
如何统计每条边通过次数?
考虑树中的一条边,如果将该边去掉将会分成两部分,可以统计该两部分的点的数量,该边的通过次数即两部分相乘一部分点数为
sz
那么另一部分即为n-sz
那么该边通过次数即sz*(n-sz)
。跑一个dfs即可统计出来。目前有
n-1
条边待分配边权,有m
个边权值,如果m>n-1
,把前几个大数乘起来(保证所有边权乘起来等于k
)分配给经过边数最多的那条边。如果m==n-1
那么就一个边一个数贪心经过次数多的边权重大。如果m最后几条边权重是1。
(之前没考虑m>n-1
这种情况wwwsTO)
#define IO ios::sync_with_stdio(false);
cin.tie();
cout.tie(0)
#pragma GCC optimize(2)
#include
#include
#include
using namespace std;
typedef long long ll;
typedef pair pii;
const int mod=1e9+7;
const int N=100010,M=2*N;
int n,m;
int h[N],e[M],ne[M],idx;
vectorw;
ll sz[N],p[N];
void add(int a,int b)
{
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
void dfs(int u,int fa)
{
sz[u]=1;
for(int i=h[u];
i!=-1;
i=ne[i])
{
int j=e[i];
if(j==fa) continue;
dfs(j,u);
sz[u]+=sz[j];
w.push_back(1ll*sz[j]*(n-sz[j]));
}
}
void init(int n)
{
for(int i=0;
i<=n;
i++) h[i]=-1;
w.clear();
idx=0;
}
int main()
{
IO;
int T;
cin>>T;
while(T--)
{
cin>>n;
init(n);
for(int i=1;
i>a>>b;
add(a,b);
add(b,a);
}
cin>>m;
for(int i=0;
i>p[i];
sort(p,p+m);
reverse(p,p+m);
dfs(1,-1);
sort(w.begin(),w.end());
reverse(w.begin(),w.end());
ll res=0;
if(m<=w.size())
{
for(int i=0;
i
F-Reverse and Swap
F题Reverse and Swap
留个坑,回来补这题数据结构
2020/8/23补
方法一:
首先这题单点修改,区间查询无疑线段树可以做。
考虑如何进行区间交换?
由于数组线段树固定做儿子和右儿子的下标父节点 u 左孩子u<<1 右孩子u<<1|1
,传统方式不宜进行区间交换,因此采用指针方式记录左右孩子(主席树方式)那么区间交换直接交换左右孩子即可,而区间反转则是递归交换左右子树直到叶子节点。
尝试用懒标极维护区间操作:lazy
看成一个二进制数(状态压缩),对于一个节点如果lazy^id!=0
说明id
中的1所在的位置lazy
中也是1那么表示需要该节点的左右子树。
于是区间反转则是在根节点直接打上标记tree[root].lazy^=(1<<(k+1))-1;
区间交换则tree[root].lazy^=1<<(k+1);
参考大佬题解
// [1 2 3 45 6 7 8]1000id:3
// [1 2 3 4][5 6 7 8]0100id:2
// [1 2] [3 4][5 6] [7 8]0010id:1
// [1][2][3][4][5][6][7][8]0001id:0
#define IO ios::sync_with_stdio(false);
cin.tie();
cout.tie(0)
#pragma GCC optimize(2)
#include
#include
#include
看standing发现了一个神奇的做法自己写一下
方法二:
把线段树看成一层一层的,可以发现反转和交换操作都是在同层进行,因此可以以层数记录lazy
,方法一是用swap
操作实现reverse
操作,同样其实也可以用reverse
操作实现swap
:可以先把上一层每个区间进行reverse
然后把该层的每个区间再reverse
实际上实现的就是swap
操作。
之前说过传统线段树不宜进行区间反转等操作,这个方法秒在不进行区间反转操作,只记录每层的区间是否需要进行反转,仅仅在查询和更改时候进行相应的坐标变化即可。
// [1 2 3 45 6 7 8]level:3
// [1 2 3 4][5 6 7 8]level:2
// [1 2] [3 4][5 6] [7 8]level:1
// [1][2][3][4][5][6][7][8]level:0
// 区间交换 level=2 只需要先反转level=3 然后再反转level=2即可
#define IO ios::sync_with_stdio(false);
cin.tie();
cout.tie(0)
#pragma GCC optimize(2)
#include
#include
#include
要加油哦~
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- codeforces B. Young Explorers
- codeforces C. Mere Array
- codeforces D. Omkar and Bed Wars
- codeforces C. Omkar and Waterslide
- codeforces B. Omkar and Infinity Clock
- codeforces B. Ternary Sequence
- 题库-CF|【Codeforces Round 370 (Div 2) E】【线段树 等比数列 区间合并】Memory and Casinos 赌场区间[l,r] l进r先出的概率
- 题库-CF|【Codeforces Round 263 (Div 2)C】【贪心 哈弗曼思维】Appleman and Toastman 每个非1size子树延展为2子树的最大权
- Codeforces|Codeforces Round #605 (Div. 3) D. Remove One Element
- Codeforces|Codeforces Round #643 (Div. 2) B.Young Explorers