2022年10月上旬刷题记录

在这里插入图片描述

abc272g摩尔投票

给定一个长度为 n的序列 , 序列中每一个数互不相同, 这个时候想要选择一个数m使得 all数mod m之后, 存在绝对众数.(数量占 一半以上)

1随机化思想

a[i]=ans+k1*mod

a[j]=ans+k2*mod

所以rand找i和j求差值,然后枚举m|abs(ai-aj)
check代价是On



2摩尔投票

算法笔记戳
例题,求区间绝对众数和求个数大于n/3的众数

class Solution {
    
    
public:
    vector<int> majorityElement(vector<int>& nums) {
    
    
        int n=nums.size();
        int a=0,b=0,x=0,y=0;
        for(auto i:nums){
    
    
            if(a==i&&x)x++;
            else if(b==i&&y)y++;
            else if(!x)a=i,x++;
            else if(!y)b=i,y++;
            else x--,y--;
        }
        vector<int>v;
        x=0,y=0;
        for(auto t:nums){
    
    
            if(t==a)x++;
            if(t==b)y++;
        }
        if(x>n/3)v.push_back(a);
        if(y>n/3&&b!=a)v.push_back(b);
        return v;
    }
};



cf169div2E

#include<bits/stdc++.h>
// #define int long long
#define ls u<<1
#define rs u<<1|1
using namespace std;
const int N=1e5+10;
int n,tr[N],dep[N],dfn[N],m,op,u,d,x,sz[N];
int a[N*4],idx,lazy[N*4];
vector<int>g[N];
void dfs(int u,int fa=0){
    
    
    dep[u]=dep[fa]+1;
    dfn[u]=++idx;
    sz[u]=1;
    for(auto j:g[u]){
    
    
        if(j==fa)continue;
        dfs(j,u);
        sz[u]+=sz[j];
    }
}
void add(int x,int c){
    
    
    for(int i=x;i<=n;i+=i&-i)tr[i]+=c;
}
int sum(int x){
    
    
    int ans=0;
    for(int i=x;i;i-=i&-i)ans+=tr[i];
    return ans;
}
void pushdown(int u){
    
    
    int &x=lazy[u];
    if(x==0)return;
    lazy[ls]+=x,a[ls]+=x;
    lazy[rs]+=x,a[rs]+=x;
    lazy[u]=0;
}
void modify(int u,int ql,int qr,int v,int l=1,int r=n){
    
    
    if(ql>qr)return;
    if(ql<=l&&r<=qr){
    
    
        a[u]+=v;
        lazy[u]+=v;
        return;
    }
    if(ql>r||qr<l)return;
    pushdown(u);
    int mid=l+r>>1;
    modify(ls,ql,qr,v,l,mid);
    modify(rs,ql,qr,v,mid+1,r);
}
int query(int u,int x,int l=1,int r=n){
    
    
    if(l==r)return a[u];
    int mid=l+r>>1;
    pushdown(u);
    if(x<=mid)return query(ls,x,l,mid);
    return query(rs,x,mid+1,r);
}
signed main(){
    
    
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<n;i++){
    
    
        int a,b;
        cin>>a>>b;
        g[a].push_back(b);
        g[b].push_back(a);
    }
    dfs(1);
    while(m--){
    
    
        cin>>op;
        if(op==0){
    
    
            cin>>u>>x>>d;
            if(u==1){
    
    add(d+1,x);continue;}
            if(d+1<dep[u])modify(1,dfn[u]-d,min(dfn[u]+d,dfn[u]+sz[u]-1),x);
            else{
    
    
                add(d-dep[u]+2,x);
                int l=d-dep[u]+3;
                //dfn[u]-dep[u]=ans-l
                //ans=dfn[u]-dep[u]+l
                int r=min(dfn[u]+d,dfn[u]+sz[u]-1);
                modify(1,dfn[u]-dep[u]+l,r,x);
            }
        }
        else{
    
    
            cin>>u;
            cout<<sum(n)-sum(dep[u]-1)+query(1,dfn[u])<<'\n';
        }
    }
}

edu 64 D

树形dp计数

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10,M=2*N;
//不存在10这样的序列
int f[N][4],n,ans;
/*
0 00
1 01
2 10
3 11
*/
int h[N],e[M],ne[M],idx,w[M];
void add(int a,int b,int c){
    
    
    e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int fa=0){
    
    
    int a[4];
    memset(a,0,sizeof a);
    for(int i=h[u];~i;i=ne[i]){
    
    
        int j=e[i];
        if(j==fa)continue;
        dfs(j,u);
        if(w[i]==0){
    
    
            a[0]=f[j][0]+1;
            a[1]=f[j][1]+f[j][3];
            a[2]=0;
            a[3]=0;
        }
        else{
    
    
            a[0]=0;
            a[1]=0;
            a[2]=f[j][2]+f[j][0];
            a[3]=f[j][3]+1;
        }
        //答案跨越u节点,在两颗子树之间
        //00
        ans+=a[0]*f[u][0]*2;
        //01
        ans+=a[0]*f[u][1]+a[0]*f[u][3]+a[1]*f[u][0];
        //10
        ans+=a[2]*f[u][3]+a[3]*f[u][2]+a[3]*f[u][0];
        //11
        ans+=a[3]*f[u][3]*2;
        
        
        //答案经过u节点,在一棵子树内
        ans+=a[0]*2+a[1]+a[2]+a[3]*2;
        
        for(int i=0;i<4;i++)f[u][i]+=a[i];
    }
    //答案经过u节点,在一棵子树内
    // ans+=2*f[u][0]+f[u][1]+f[u][2]+2*f[u][3];
}
signed main(){
    
    
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>n;
    memset(h,-1,sizeof h);
    for(int i=1;i<n;i++){
    
    
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
        add(b,a,c);
    }
    dfs(1);
    cout<<ans;
}

并查集组合数

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N=2e5+10;
int n,p[2][N],sz[2][N],ans;
int find(int o,int x){
    
    
    if(p[o][x]==x)return x;
    return p[o][x]=find(o,p[o][x]);
}
signed main(){
    
    
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++)p[0][i]=p[1][i]=i,sz[0][i]=sz[1][i]=1;
    for(int i=1;i<n;i++){
    
    
        int a,b,c;
        cin>>a>>b>>c;
        a=find(c,a),b=find(c,b);
        if(a!=b){
    
    
            p[c][a]=b;
            sz[c][b]+=sz[c][a];
        }
    }
    for(int i=1;i<=n;i++){
    
    
        int a=find(0,i);
        int b=find(1,i);
        ans+=(sz[0][a]-1)*(sz[1][b]-1);
        if(a==i)ans+=sz[0][a]*(sz[0][a]-1);
        if(b==i)ans+=sz[1][b]*(sz[1][b]-1);
    }
    cout<<ans;
}

E. Special Segments of Permutation

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N=2e5+10;
int n,a[N],ans;
signed main(){
    
    
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=2;i<n;i++){
    
    
        set<int>S;
        if(a[i-1]>a[i]||a[i+1]>a[i])continue;
        for(int j=i-1;j>=1;j--){
    
    
            if(a[j]>a[i])break;
            S.insert(a[j]);
        }
        for(int j=i+1;j<=n;j++){
    
    
            if(a[j]>a[i])break;
            if(S.count(a[i]-a[j]))ans++;
        }
    }
    cout<<ans;
}

概率dp

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353;
const int N=5050;
int n,x,ans,f[N][N],sum[N][N],inv[N],s[N];
//f[i][j]表示拿了j张牌且最后一次拿到了i的概率
signed main(){
    
    
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++){
    
    
        cin>>x;
        s[x]++;
    }
    inv[0]=inv[1]=1;
    for(int i=2;i<=n;i++)inv[i]=(mod-mod/i*inv[mod%i]%mod)%mod;
    sum[0][0]=sum[1][0]=1;
    for(int i=1;i<=n;i++){
    
    //枚举以i为结束牌
        for(int j=1;j<=i;j++){
    
    //枚举拿了多少张牌
            f[i][j]=sum[(i-1)&1][j-1]*s[i]%mod*inv[n-j+1]%mod;
            ans+=f[i][j]*(s[i]-1)%mod*inv[n-j]%mod;
            ans%=mod;
            sum[i&1][j]=(sum[(i-1)&1][j]+f[i][j])%mod;
        }
    }
    cout<<ans;
}

子集dp牛客练习赛E

#include<bits/stdc++.h>
using namespace std;
const int N=24,M=1<<N;
int n,f[M],a[100010];
signed main(){
    
    
    ios::sync_with_stdio(0);cin.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=n;i++){
    
    
        int x=0;
        for(int j=i;j<=n;j++){
    
    
            if(x&a[j])break;
            x|=a[j];
            f[x]=x;
        }
    }
    int m=M-1;
    for(int i=0;i<=m;i++){
    
    
        for(int j=0;j<=23;j++){
    
    
            if(i>>j&1)f[i]=max(f[i],f[i-(1<<j)]);
        }
    }
    int ans=0;
    for(int i=0;i<=m;i++)ans=max(ans,f[i]+f[m^i]);
    cout<<ans;
}

牛客练习赛32C矩阵快速幂

#include<bits/stdc++.h>
#define int long long
#define mod 998244353
using namespace std;
int A[4][4]={
    
    
    1,1,0,0,
    1,0,0,0,
    1,0,1,1,
    0,0,1,0
};
struct node{
    
    
    int a[4][4];
    node(){
    
    memset(a,0,sizeof a);}
    void init(){
    
    memcpy(a,A,sizeof a);}
    node operator*(const node&B)const{
    
    
        auto &b=B.a;
        node C;
        auto &c=C.a;
        for(int i=0;i<4;i++){
    
    
            for(int j=0;j<4;j++){
    
    
                for(int k=0;k<4;k++){
    
    
                    c[i][j]+=a[i][k]*b[k][j]%mod;
                    c[i][j]=(c[i][j]%mod+mod)%mod;
                }
            }
        }
        return C;
    }
    node qpow(int b){
    
    
        node ans;ans.init();b--;
        node A;memcpy(A.a,a,sizeof a);
        while(b){
    
    
            if(b&1)ans=ans*A;
            b/=2;
            A=A*A;
        }
        return ans;
    }
}a,ans;
int n;
void pr(node A){
    
    
    for(int i=0;i<4;i++)cout<<A.a[0][i]<<" ";
    cout<<'\n';
}
signed main(){
    
    
    cin>>n;
    node t;
    t.a[0][0]=0;
    t.a[0][1]=0;
    t.a[0][2]=1;
    t.a[0][3]=0;
    node A;A.init();
//     pr(A);
    A=A.qpow(n);
//     pr(A);
    t=t*A;
//     pr(t);
    cout<<t.a[0][1];
}

牛客练习赛80C

可以矩阵快速幂来写,记得封装矩阵乘法运算的时候要memset(c.a,0,sizeof c.a)

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=100019;
struct node{
    
    
    int a[10][10];
    void init(){
    
    
        memset(a,0,sizeof a);
        for(int j=1;j<=9;j++)a[1][j]=1;
    }
    node(){
    
    
        memset(a,0,sizeof a);
        for(int i=1;i<=9;i++){
    
    
            for(int j=1;j<=i;j++){
    
    
                a[i][j]=1;
            }
        }
    }
    node operator*(const node&b)const{
    
    
        node c;
        memset(c.a,0,sizeof c.a);
        for(int i=1;i<=9;i++){
    
    
            for(int j=1;j<=9;j++){
    
    
                for(int k=1;k<=9;k++){
    
    
                    c.a[i][j]+=a[i][k]*b.a[k][j];
                    c.a[i][j]%=mod;
                }
            }
        }
        return c;
    }
    void pr(){
    
    
        for(int i=1;i<=9;i++){
    
    
            for(int j=1;j<=9;j++)cout<<a[i][j]<<" ";
            cout<<'\n';
        }
        cout<<"****************************"<<'\n';
    }
}A,E;
node qpow(node a,int b){
    
    
    node ans;
    while(b){
    
    
        if(b&1)ans=ans*a;
        b/=2;
        a=a*a;
    }
    return ans;
}
int n;
signed main(){
    
    
    cin>>n;
    A.init();
    A=A*qpow(E,n-1);
    cout<<A.a[1][1];
}


猜你喜欢

转载自blog.csdn.net/supreme567/article/details/127229688