0%

cfR#672div2(A~D)

round 672 div2

A : 思维

根据题意,显然n=2时只要是逆序的就no,考虑一般情况,最坏时候即整个为逆序排列,此时所需次数为$\frac{n*(n-1)}{2}$,显然得出结论,当仅最坏不可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include<iostream>
#define fuck() int t;cin>>t;while(t--)
using namespace std;

int main()
{
string y="YES",N="NO";
fuck(){
int n;cin>>n;
if(n==2){
int a,b;cin>>a>>b;
if(a>b)cout<<N<<endl;
else cout<<y<<endl;
}else{
int a,b;int cnt=0;
cin>>b;
for(int i=2;i<=n;++i){
a=b;cin>>b;
if(a>b)cnt++;
}
if(cnt==n-1)cout<<N<<endl;
else cout<<y<<endl;
}
}
return 0;
}

B : 思维

不难发现,两个数的按位与大于按位异或,当仅两数的二进制最高位位数相等

我第一次用了log,wa#3,可能是有误差,直接位运算找最高位即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include<iostream>
#define fuck() int t;cin>>t;while(t--)
using namespace std;
typedef long long ll;
int cn(int tmp){//这里只要能区分就行了,哪怕结果没有意义
int cnt=0;
while(tmp){
tmp>>=1;
cnt++;
}
return cnt;
}
int main()
{

fuck(){
ll n;cin>>n;
map<int,ll> dic;int tmp;
for(int i=1;i<=n;++i){
cin>>tmp;
if(tmp==0)continue;
dic[cn(tmp)]+=1;
}
ll cnt=0;
for(auto i:dic){
if(i.second>=2){
cnt+=(((ll)i.second-1)*i.second)/2;
}
}
cout<<cnt<<endl;
}
return 0;
}

C1 : DP

由题意,设置dp[maxn][2],dp[i][0]为减去这一个数的最大可能情况

过程中维护ma0和ma1,转移方程为$dp[i][0]=ma1-in[i],dp[i][1]=ma0+in[i]$

每次转移完成更新ma1,ma0,最后结果为$max(ma1,ma0)$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<iostream>
#define fuck() int t;cin>>t;while(t--)
using namespace std;
typedef long long ll;
const int maxn=3e5+3;
int in[maxn];
ll dp[maxn][2];

int main()
{
fuck(){
int n,q;cin>>n>>q;
for(int i=1;i<=n;++i){
cin>>in[i];
}
dp[0][0]=0;dp[0][1]=0;
ll ma1=0,ma0=0;
for(int i=1;i<=n;++i){
dp[i][1]=ma0+in[i];
dp[i][0]=ma1-in[i];
ma0=max(ma0,dp[i][0]);
ma1=max(ma1,dp[i][1]);
}
cout<<max(ma1,ma0)<<endl;
}
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//下文的波峰波谷
#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+10;
long long d[maxn];
int in[maxn];
int main()
{
int n,q;
int t;cin>>t;while(t--){
cin>>n>>q;
long long ans=0;
for(int i=1;i<=n;++i){
cin>>in[i];
}
in[0]=0;
for(int i=1;i<=n;++i){
d[i]=in[i]-in[i-1];
}
for(int i=1;i<=n;++i){
if(d[i]>0){
ans+=d[i];
}
}
cout<<ans<<endl;
}
return 0;
}

C2 : 贪心,思维

hard版本就是可以交换数,再来看整个过程

显然还有办法,就是波峰波谷,只取这些数即可,可以直接模拟求,也可以计算差分数组中正数的和.

转换之后,每次转换至多改变4个差分值,十分简单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+10;
int in[maxn];
int main()
{
int t;cin>>t;while(t--){
memset(in,0,sizeof in);
int n,q;cin>>n>>q;
for(int i=1;i<=n;++i){
cin>>in[i];
}
long long ans=0;
for(int i=1;i<=n;++i){
if(in[i]-in[i-1]>0)ans+=in[i]-in[i-1];
}
cout<<ans<<endl;
int l,r;
while(q--){
cin>>l>>r;
if(l==r){
cout<<ans<<endl;
}else if(l+1==r){
long long tmp=max(in[l]-in[l-1],0)+max(in[r]-in[l],0)+max(in[r+1]-in[r],0);
swap(in[l],in[r]);
ans+=max(in[l]-in[l-1],0)+max(in[r]-in[l],0)+max(in[r+1]-in[r],0)-tmp;
cout<<ans<<endl;
}else {
long long tmp=max(in[l]-in[l-1],0)+max(in[l+1]-in[l],0)+max(in[r+1]-in[r],0)+max(in[r]-in[r-1],0);
swap(in[l],in[r]);
ans+=max(in[l]-in[l-1],0)+max(in[l+1]-in[l],0)+max(in[r+1]-in[r],0)+max(in[r]-in[r-1],0)-tmp;
cout<<ans<<endl;
}
}
}
return 0;
}

D : 离散化

对时刻离散化后,遍历时刻,仅计算,当前时刻刚刚亮的灯和之前就亮的灯的排列,因为题意中,不同时刻也不能开同几盏灯.

注意这ans可能是负的….(妈的我也不知道为什么)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=3e6+10;
const int mod=998244353;
int inv[N], fac[N];
void init(){
fac[0] = 1; inv[0] = inv[1] = 1;
for(int i = 1; i <= 1000000; i++)fac[i] = 1ll * fac[i - 1] * i % mod;
for(int i = 2; i <= 1000000; i++)inv[i] = (1ll * mod - mod / i)* inv[mod % i] % mod;//digui inv
for(int i = 2; i <= 1000000; i++)inv[i] = 1ll * inv[i] * inv[i - 1] % mod;
}
int C(int n, int m){
if(m > n || m < 0)return 0;
return 1ll * fac[n] * inv[m] % mod* inv[n - m] % mod;
}
const int maxn=3e6+10;
int l[maxn],r[maxn];
int a[maxn*2];
int tot,cnt;
int d[maxn];
int wos[maxn];
int fts[maxn];
int main()
{
int n,k;cin>>n>>k;int x,y;
for(int i=1;i<=n;++i){
cin>>x>>y;
l[i]=x;r[i]=y;
a[++tot]=x;a[++tot]=y;
}
sort(a+1,a+1+tot);
for(int i=1;i<=tot;++i){
if(a[i]!=a[i+1]){
a[++cnt]=a[i];
}
}
for(int i=1;i<=n;++i){
int lll=lower_bound(a+1,a+1+cnt,l[i])-a;
int rrr=lower_bound(a+1,a+1+cnt,r[i])-a;
d[lll]+=1;d[rrr+1]-=1;
fts[lll]+=1;
}
for(int i=1;i<=cnt;++i){
wos[i]=d[i]+wos[i-1];
}
init();
long long ans=0;
for(int i=1;i<=cnt;++i){
ans=(ans+C(wos[i],k)-C(wos[i]-fts[i],k))%mod;
}
cout<<(ans+mod)%mod<<endl;
return 0;
}