简单记录
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)

#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;
}

浙公网安备 33010602011771号