简单记录

P1268 树的重量

先考虑二,三个,然后考虑四个,发现这种向外延展的思路.

看树形背包发现动态开数组

这个主要是针对N*W这种的开二维数组

    //如果你感觉这里的二维数组很难定义,可以先开一个一维的 int 数组,假设名字为 pool;等到读入了 N, W 后再这样声明
    //但是,你甚至可以开vector然后resize,完全动态分配内存.
    //这个存在一些问题,就是这个内存分配和n,w持久绑定,修改了n,w下标会跟着改变,注意一下就行.
    int (&dp)[n+1][w+1]=decltype(dp)(pool);//decltype 推断

单调栈?悬线法?

区间异或翻转

可以差分 打标(对于未来的反转情况)

#include<bits/stdc++.h>
#define int long long
#define F(i,i0,n) for(int i=i0;i<=n;i++)
const int N=1e4+5;
using namespace std;
int n,a[N],d[N]; 
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>n;
    F(i,1,n){
        char x;cin>>x;
        a[i]=(x=='F')?1:0;
    }
    int ant=0,ans=INT_MAX;
    F(k,1,n){
        int cnt=0,fail=0;
        memset(d,0,sizeof(d));
        int tag=0;
        F(i,1,n){
            tag^=d[i];
            if(!(a[i]^tag)){
                if(i+k-1>n){
                    fail=1;
                    break;
                }
                d[i+k]^=1;
                tag^=1;
                cnt++;
            }
        }
        if(fail)continue;
        if(cnt<ans){
            ans=cnt;
            ant=k;
        }
    }
    cout<<ant<<" "<<ans;
    
    return 0;
}

km

#include<bits/stdc++.h>
#define F(i0,i1,i2) for(int i0=i1;i0<=i2;++i0)
#define N 1000005
using namespace std;
inline int rd(){
    int x=0,f=0;char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')f=1;ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<3)+(x<<1)+ch-48;
        ch=getchar();
    }
    return f?-x:x;
}
struct Node{
    int v,nt;
}e[N];
int p[N],id;
void add(int x,int y){
    e[++id]={y,p[x]};
    p[x]=id;
}
int n,m,el;
int f[N],mat[N];
int l[N],r[N];
bool km(int x){
    f[x]=1;
    for(int i=p[x];i;i=e[i].nt){
        int v=e[i].v;
        if(f[v])continue;
        f[v]=1;
        if(!mat[v]||km(mat[v])){
            mat[v]=x;
            return 1;
        }
    }
    return 0;
}
signed main(){
    n=rd(),m=rd(),el=rd();
    F(i,1,el){
        int x=rd(),y=rd();
        add(x,y+n);
    }
    int ans=0;
    F(i,1,n){
        memset(f,0,sizeof(f));
        ans+=km(i);
    }
    cout<<ans<<endl;
    return 0;
}

整数分块

#include<bits/stdc++.h>
#define int long long
#define F(i,i0,n) for(int i=i0;i<=n;i++)
using namespace std;
inline int rd(){
    int f=0,x=0;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=1;ch=getchar();}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-48;ch=getchar();}
    return f?-x:x;
}
const int N=5e4+5;
int n,k;
signed main(){
    int n=rd(),k=rd();
    int sum=0;
    for(int l=1,r;l<=n;l=r+1){
        if(k/l!=0)r=min(k/(k/l),n);
        else r=n;
        sum+=(r-l+1)*(k/l)*(l+r)>>1; 
    }
    cout<<n*k-sum;
    return 0;
}

糖果传递

不懂就看blogs

signed main(){
    n=rd();
    int s=0;
    F(i,1,n)a[i]=rd(),s+=a[i];
    ave=s/n;
    F(i,1,n)a[i]-=ave;
    F(i,1,n)c[i]=c[i-1]+a[i];
    int x1=(n+1)/2;
    nth_element(c+1,c+x1,c+1+n);
    int ans=0;
    F(i,1,n)ans+=abs(c[x1]-c[i]);
    cout<<ans<<'\n';
    return 0;
}

什么是dinic?

链与链无关的树形dp可以dfn序,优化空间。(这里保证了二叉所以说是now+1和now+2)

Alt text

#include<bits/stdc++.h>
#define int long long
#define F(i,i0,n) for(int i=(i0);i<=(n);++i)
#define DF(i,i0,n) for(int i=(i0);i>=(n);--i)
#define pii pair<int,int>
#define fr first
#define sc second
using namespace std;
inline int rd(){
    int f=0,x=0;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=1;ch=getchar();}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-48;ch=getchar();}
    return f?-x:x;
}
const int N=1e6+5,M=2e2+5;
int n;
int ls[N],rs[N],a[N],b[N],c[N];
int dp[M][M][M],dfn[N];
void dfs(int u,int now,int x,int y){
    dfn[u]=now;
    if(u>=n){
        F(i,0,x)
            F(j,0,y)dp[dfn[u]][i][j]=c[u]*(a[u]+i)*(b[u]+j);
        return ;
    }
    else {
        dfs(ls[u],now+1,x+1,y);
        dfs(rs[u],now+2,x,y+1);
        F(i,0,x)
            F(j,0,y)
                dp[dfn[u]][i][j]=min(dp[dfn[ls[u]]][i+1][j]+dp[dfn[rs[u]]][i][j],dp[dfn[ls[u]]][i][j]+dp[dfn[rs[u]]][i][j+1]);
    }
    
}
signed main(){
    n=rd();
    F(i,1,n-1){
        ls[i]=rd();
        rs[i]=rd();
        if(ls[i]<0)ls[i]=n-ls[i]-1;
        if(rs[i]<0)rs[i]=n-rs[i]-1;
    }
    F(i,n,2*n-1){
        a[i]=rd(),b[i]=rd(),c[i]=rd();
    }
    dfs(1,1,0,0);
    cout<<dp[dfn[1]][0][0]<<'\n';
    return 0;
}


图上状压的有效降低复杂度(减少状态)方法--拆开枚举

A-B的拓扑路径转化为A-sta-B这样

void Dp(){
    dp[0]=1;
    F(sta,1,(1<<n)-1){
        dp[sta]=Rch[sta]=0;
        F(u,0,n-1)if(sta&(1<<u))Rch[sta]|=e[u];
    }
    F(sta,0,(1<<n)-1){
        F(u,0,n-1){
            if(e[u]&sta||(1<<u)&sta)continue;
            dp[sta|(1<<u)]+=dp[sta];
        }
    }
    int U=(1<<n)-1;
    dp[0]=1;
    F(y,0,n-1){
        F(sta,0,(1<<n)-1)if(!(sta&(1<<y))){
            int S=U^sta^(1<<y);
            if(e[y]&sta||Rch[S]&(sta|(1<<y)))continue;
            for(int i=sta;i;i-=lowbit(i))
                ans[y][__lg(lowbit(i))]+=dp[sta]*dp[S];
        }
    }
}

区间子区间->前缀问题

二维偏序选点->坐标轴上贪心选择

我该怎么描述
所以说看9.week2的blog吧

#include<bits/stdc++.h>
#define int long long
#define F(i,i0,n) for(int i=(i0);i<=(n);i++)
#define pii pair<int,int>
#define fr first
#define sc second
#define pb push_back
using namespace std;
inline int rd(){
    int f=0,x=0;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=1;ch=getchar();}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-48;ch=getchar();}
    return f?-x:x;
}
const int N=2e5+5;
// x t+x y t-x
int n;
struct Node{
    int q,x,y;
    mutable int n;
    bool operator < (const Node &_)const{
        return x<_.x;
    }
}a[N];
bool cmp(const Node &o,const Node &_){
    return o.y==_.y?o.x>_.x:o.y>_.y;
}
multiset<Node>s;
int ans;
void solve(){
    F(i,1,n){
        if(a[i].q==1){
            while(a[i].n){
                auto it=s.lower_bound({0,a[i].x,0,0});
                if(it==s.end())break;
                if(it->n>a[i].n){
                    ans+=a[i].n;
                    it->n-=a[i].n;
                    break;
                } 
                ans+=it->n;
                a[i].n-=it->n;
                s.erase(it);
            } 
        }
        else {
            s.insert(a[i]);
        }
    }
    cout<<ans<<'\n';
}
signed main(){
    n=rd();
    F(i,1,n){
        a[i].q=rd();
        int t=rd(),x=rd();
        a[i].x=t+x,a[i].y=t-x;
        a[i].n=rd();
    }
    sort(a+1,a+1+n,cmp);
    solve();
    return 0;
}



李超线段树?

posted @ 2023-10-20 18:42  ussumer  阅读(27)  评论(0)    收藏  举报