Codeforces Round #672 (Div. 2)
题外话
恢复性训练
A
题意
问你一组数列排成非递减的数列, 是否在$ n * (n-1)/2-1 $次数中完成
思路
妈妈的, 我把自己演了,写了个假代码
直接判断这个数组是否是单调递减的,是的话输出no ,否则输出yes ,至于为什么,可以画个图理解一下(很简单的图,我就不管了)
代码
#include <cstdio>
#include <algorithm>
#include<iomanip>
#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <cstring>
#include<stack>
#include <cassert>
#include<map>
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define drep(i,a,b) for(i=a;i>=b;i--)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define pb push_back
#define de(x) cerr<<#x<<" = "<<x<<endl
#define __i __int128
#define pn printf("\n");
#define pk printf(" ");
#define p(n) printf("%d",n);
#define pln(n) printf("%d\n",n);
#define s(n) scanf("%d",&n);
#define ss(n) scanf("%s",n);
#define ps(n) printf("%s",n);
#define sld(n) scanf("%lld",&n);
#define pld(n) printf("%lld",n);
#define slf(n) scanf("%lf",&n);
#define plf(n) printf("%lf",n);
#define sc(n) scanf("%c",&n);
#define pc(n) printf("%c",n);
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0)
using namespace std;
//using namespace __gnu_pbds;
typedef long long LL;
typedef pair<int,int> pii;
typedef pair<LL,LL> pLL;
const int inf=0x7fffffff;
const int N =3.1e5;
const int maxn = 200010;
void clear(unsigned char *pta, int size )
{//结构体初始化
while(size>0)
{
*pta++ = 0;
size --;
}
}
LL n, k, m ;
LL ar[N],br[N],cr[200005],dr[200005];
LL i,j,g;
LL MOD = 998244353 ;
LL fac[N],inv_fac[N];
//快速幂
LL qpow(LL x, LL y ){
x%=MOD;
long long res=1%MOD;
while(y){
if(y&1)res=res*x%MOD;
y>>=1;
x=x*x%MOD;
}
return res;
}
void pre(){
fac[0] =1 ;
for(int i=1;i<N;i++){
fac[i] =fac[i-1] * i %MOD;
}
inv_fac[N - 1 ] = qpow(fac[N - 1] , MOD-2 ) ;
for(int i =N-2 ;i>=0 ;i--){
inv_fac[i] = inv_fac[i+1] * (i+1) %MOD;
}
}
LL C (LL a ,LL b){
if(a<0 || b> a )//因为是C(a,b) 所以b《= a
{
return 0;
}
return fac[a] * inv_fac[b] % MOD *inv_fac[a-b]%MOD;//a 的阶乘 / ( b的阶乘 * (a-b的阶乘))
}
void answer(){
sld(n);LL cnt =0 ;
for(int i=1;i<=n;i++)sld(ar[i]);
for(int i=1;i<=n;i++){
if(ar[i]>ar[i+1] && i+1<=n ){
cnt ++ ;
}
}
if(cnt == n-1 )printf("NO\n");
else printf("YES\n");
}
int main()
{
// ios::sync_with_stdio(0);
// cin.tie(0), cout.tie(0);
// pre();
int t;s(t);
while(t--)
answer();
return 0;
}
B
题意
给你一串数, 然后让你找出来 两个数的& 大于等于 两个数的xor 的数量
思路
一看有xor 和 & 一定要想到 二进制 , 然后通过二进制下的数字,发现 & 的 >= xor 只能是当 两个数字的最大位置的 1 位置相同才行。
所以存一下每个数的 最大位置上的 1 的位置 ,然后求和即可
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <string>
#include <sstream>
#include <iostream>
#include <time.h>
#include <queue>
#include <list>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <string.h>
#include <bitset>
#define sf scanf
#define pf printf
#define lf double
#define p123 printf("123\n");
#define pn printf("\n");
#define pk printf(" ");
#define p(n) printf("%d",n);
#define pln(n) printf("%d\n",n);
#define s(n) scanf("%d",&n);
#define ss(n) scanf("%s",n);
#define ps(n) printf("%s",n);
#define sld(n) scanf("%lld",&n);
#define pld(n) printf("%lld",n);
#define slf(n) scanf("%lf",&n);
#define plf(n) printf("%lf",n);
#define sc(n) scanf("%c",&n);
#define pc(n) printf("%c",n);
//#define gc getchar();
#define ll long long
#define re(n,a) memset(n,a,sizeof(n));
#define len(a) strlen(a)
#define eps 1e-13
#define zero(x) (((x) > 0? (x):(-x)) < eps)
using namespace std;
int a[100050];
int b[1000];
#include <stdio.h>
int main(){
int T;
s(T)
while(T --){
int n;
s(n)
re(b,0);
for(int i = 0; i < n; i ++){
s(a[i])
int flag = 0;
while(a[i] != 0){
a[i] >>= 1;
flag ++;
}
b[flag] ++;
}
ll sum = 0ll;
for(int i = 0; i < 50; i ++){
ll temp = b[i];
sum += (temp*(temp-1ll))>>1;
}
pld(sum) pn
}
return 0;
}
C1
题意
简单版本的就是给你一组数,然后让你找出来这样一个序列 ($ a_1-a_2+a_3-a_4+... +a_n $ )使得 这个结果是最大的情况
思路
因为是个简单版本的,可以直接暴力求局部最大和最小, 然后相加一下就行
代码
#include <cstdio>
#include <cstdio>
#include <algorithm>
#include<iomanip>
#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <cstring>
#include<stack>
#include <cassert>
#include<map>
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define drep(i,a,b) for(i=a;i>=b;i--)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define pb push_back
#define de(x) cerr<<#x<<" = "<<x<<endl
#define __i __int128
#define pn printf("\n");
#define pk printf(" ");
#define p(n) printf("%d",n);
#define pln(n) printf("%d\n",n);
#define s(n) scanf("%d",&n);
#define ss(n) scanf("%s",n);
#define ps(n) printf("%s",n);
#define sld(n) scanf("%lld",&n);
#define pld(n) printf("%lld",n);
#define slf(n) scanf("%lf",&n);
#define plf(n) printf("%lf",n);
#define sc(n) scanf("%c",&n);
#define pc(n) printf("%c",n);
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0)
using namespace std;
//using namespace __gnu_pbds;
typedef long long LL;
typedef pair<int,int> pii;
typedef pair<LL,LL> pLL;
const int inf=0x7fffffff;
const int N =3.1e5;
const int maxn = 200010;
void clear(unsigned char *pta, int size )
{//结构体初始化
while(size>0)
{
*pta++ = 0;
size --;
}
}
LL n, k, m ;
LL ar[N],br[N],cr[200005],dr[200005];
LL i,j,g;
LL MOD = 998244353 ;
LL fac[N],inv_fac[N];
//快速幂
LL qpow(LL x, LL y ){
x%=MOD;
long long res=1%MOD;
while(y){
if(y&1)res=res*x%MOD;
y>>=1;
x=x*x%MOD;
}
return res;
}
void pre(){
fac[0] =1 ;
for(int i=1;i<N;i++){
fac[i] =fac[i-1] * i %MOD;
}
inv_fac[N - 1 ] = qpow(fac[N - 1] , MOD-2 ) ;
for(int i =N-2 ;i>=0 ;i--){
inv_fac[i] = inv_fac[i+1] * (i+1) %MOD;
}
}
LL C (LL a ,LL b){
if(a<0 || b> a )//因为是C(a,b) 所以b《= a
{
return 0;
}
return fac[a] * inv_fac[b] % MOD *inv_fac[a-b]%MOD;//a 的阶乘 / ( b的阶乘 * (a-b的阶乘))
}
void answer(){
sld(n) ;sld(k);
for(int i=1 ;i<=n;i++)sld(ar[i]);
ar[0] = ar[n+1 ] =0 ;LL sum =0 ;
for(int i=1 ;i<=n;i++){
if(ar[i]>ar[i-1]&&ar[i] >ar[i+1 ])sum +=ar[i];
if(ar[i]<ar[i-1]&&ar[i] <ar[i+1 ])sum -=ar[i];
}
pld(sum);pn;
}
int main()
{
// ios::sync_with_stdio(0);
// cin.tie(0), cout.tie(0);
// pre();
int t;s(t);
while(t--)
answer();
return 0;
}
C2
题意
这个版本在前面的基础上添加了一个q的移动, 每次都是把两个ar[r] , ar[l] 进行交换位置, 问你交换完之后的结果
思路
这个其实要考虑的事情也不多, 因为他是两个数进行交换,
- 那么假设ar[l] < ar[r] ,那么可能ar[r] 交换之后也是局部最大的,
- 那么假设ar[l] > ar[r] ,那么可能ar[r] 交换之后也是局部最小的,
- 所以受这个交换的影响的数, 一共只有ar[l] 和 ar[r] 这两个和他们左右两边的数,
- 所以,只需要每次先把这两个数和他们左右两边的数先判断一下,是否有局部最大的数或者最小的数, 有的话就从结果中先去掉
- 之后,在交换完之后, 在进行判断在新位置上的ar[l] , ar[r] 是否是局部最大的数或者最小的数, 是的话再加进来即可
代码
#include <cstdio>
#include <algorithm>
#include<iomanip>
#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <cstring>
#include<stack>
#include <cassert>
#include<map>
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define drep(i,a,b) for(i=a;i>=b;i--)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define pb push_back
#define de(x) cerr<<#x<<" = "<<x<<endl
#define __i __int128
#define pn printf("\n");
#define pk printf(" ");
#define p(n) printf("%d",n);
#define pln(n) printf("%d\n",n);
#define s(n) scanf("%d",&n);
#define ss(n) scanf("%s",n);
#define ps(n) printf("%s",n);
#define sld(n) scanf("%lld",&n);
#define pld(n) printf("%lld",n);
#define slf(n) scanf("%lf",&n);
#define plf(n) printf("%lf",n);
#define sc(n) scanf("%c",&n);
#define pc(n) printf("%c",n);
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0)
using namespace std;
//using namespace __gnu_pbds;
typedef long long LL;
typedef pair<int,int> pii;
typedef pair<LL,LL> pLL;
const int inf=0x7fffffff;
const int N =5e5+10;
const int maxn = 200010;
void clear(unsigned char *pta, int size )
{//结构体初始化
while(size>0)
{
*pta++ = 0;
size --;
}
}
LL n, k, m ;
LL ar[N],br[N],cr[200005],dr[200005];
LL i,j,g;
set<int > big_pos , small_pos;
LL sum;
bool big(int i){
return ar[i] > max(ar[i-1],ar[i+1]);
}
bool small(int i){
return ar[i] < min(ar[i-1] , ar[i+1]);
}
void clear_pos(int pos){
// cout<<ar[pos]<<endl;
if(big(pos)&&big_pos.count(pos)){
sum -= ar[pos];
big_pos.erase(pos);
}
if(small(pos)&&small_pos.count(pos)){
sum+=ar[pos];
small_pos.erase(pos);
}
// cout<<sum<<endl;
}
void updata(int pos){
if(big(pos)&&!big_pos.count(pos)){
sum += ar[pos];
big_pos.insert(pos);
}
if(small(pos)&&!small_pos.count(pos)){
sum-=ar[pos];
small_pos.insert(pos);
}
// cout<<i<<" "<<sum<<endl;
}
void answer(){
sld(n);sld(k);
for(int i=1;i<=n;i++)sld(ar[i]);
sum =0;
ar[n+1] = 0;
big_pos.clear();
small_pos.clear();
for(int i=1;i<=n;i++){
updata(i);
}
pld(sum);pn;
for(int i=k;i>=1;i--){
int x,y ;s(x);s(y);
clear_pos(x-1); clear_pos(x); clear_pos(x+1);
clear_pos(y-1); clear_pos(y); clear_pos(y+1);
swap(ar[x],ar[y]);
updata(x-1); updata(x); updata(x+1);
updata(y-1);updata(y);updata(y+1);
pld(sum);pn;
}
}
int main()
{
// ios::sync_with_stdio(0);
// cin.tie(0), cout.tie(0);
int t;s(t);
while(t--)answer();
return 0;
}
D
题意
一共n个灯,然后每个灯有自己亮的时间l,r 然后问你是否有k个灯能同时亮着,有的话,求出一共可以选择出来的数量,没有就是0
思路
其实就是一个贪心 + 组合数学
- 首先找出同一时间亮着的灯 (这里需要自己想一个操作, 我是跟一个带佬学的用vector的pair ,设置 l 为 -1 ,r 为 1 , 之后判断second 是- 1 的)
- 然后 通过组合数 来求出这个时间的数量,
- 进行求和即可
代码
#include <cstdio>
#include <algorithm>
#include<iomanip>
#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <cstring>
#include<stack>
#include <cassert>
#include<map>
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define drep(i,a,b) for(i=a;i>=b;i--)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define pb push_back
#define de(x) cerr<<#x<<" = "<<x<<endl
#define __i __int128
#define pn printf("\n");
#define pk printf(" ");
#define p(n) printf("%d",n);
#define pln(n) printf("%d\n",n);
#define s(n) scanf("%d",&n);
#define ss(n) scanf("%s",n);
#define ps(n) printf("%s",n);
#define sld(n) scanf("%lld",&n);
#define pld(n) printf("%lld",n);
#define slf(n) scanf("%lf",&n);
#define plf(n) printf("%lf",n);
#define sc(n) scanf("%c",&n);
#define pc(n) printf("%c",n);
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0)
using namespace std;
//using namespace __gnu_pbds;
typedef long long LL;
typedef pair<int,int> pii;
typedef pair<LL,LL> pLL;
const int inf=0x7fffffff;
const int N =3.1e5;
const int maxn = 200010;
void clear(unsigned char *pta, int size )
{//�ṹ���ʼ��
while(size>0)
{
*pta++ = 0;
size --;
}
}
LL n, k, m ;
LL ar[N],br[N],cr[200005],dr[200005];
LL i,j,g;
LL MOD = 998244353 ;
LL fac[N],inv_fac[N];
//������
LL qpow(LL x, LL y ){
x%=MOD;
long long res=1%MOD;
while(y){
if(y&1)res=res*x%MOD;
y>>=1;
x=x*x%MOD;
}
return res;
}
void pre(){
fac[0] =1 ;
for(int i=1;i<N;i++){
fac[i] =fac[i-1] * i %MOD;
}
inv_fac[N - 1 ] = qpow(fac[N - 1] , MOD-2 ) ;
for(int i =N-2 ;i>=0 ;i--){
inv_fac[i] = inv_fac[i+1] * (i+1) %MOD;
}
}
LL C (LL a ,LL b){
if(a<0 || b> a )//����C��a��b�� ����b��= a
{
return 0;
}
return fac[a] * inv_fac[b] % MOD *inv_fac[a-b]%MOD;//a �Ľ׳� / �� b�Ľ׳� * ��a-b�Ľ׳ˣ���
}
void answer(){
sld(n);sld(k);
vector<pii >v;
for(int i=1 ;i<=n;i++){
int l, r ;s(l);s(r);
v.pb({l,-1});v.pb({r,1});
}
sort(v.begin(), v.end());
LL sum =0 , cnt =0 ;
for(int i=0;i<v.size();i++){
sum -= v[i].se;
if(v[i].se==-1){
cnt = (cnt + C(sum - 1 , k -1 ))%MOD;
// cout<<cnt<<" ,"<<sum<<endl;
}
// cout<<sum<<endl ;
}
pld(cnt);pn;
}
int main()
{
// ios::sync_with_stdio(0);
// cin.tie(0), cout.tie(0);
pre();
// int t;s(t);
// while(t--)
answer();
return 0;
}