虎
贪心考虑边的匹配,能匹配掉的尽量在下面匹配掉,不能匹配的,如果可以上传(父亲节点到该节点的边没有限制,或者有限制并且为白色边),就上传上去,如果不能上传,ans++
code
#include<bits/stdc++.h>
#define gc getchar()
#define getch while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=gc;}
#define getnu while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+ch-'0';ch=gc;}
using namespace std;
inline int read(){int s=0,f=1;char ch=gc;getch;getnu;return s*f;}
const int maxn=1e6+10;
int head[maxn],ver[maxn*2],nxt[maxn*2],col[maxn*2],lim[maxn*2],tot,ans;
void add(int x,int y,int coler,int limm){ver[++tot]=y,nxt[tot]=head[x],col[tot]=coler,lim[tot]=limm,head[x]=tot;}
bool dfs(int x,int fa,int Col,int Lim){
int res=0;
for(int i=head[x],y;i;i=nxt[i]){
if((y=ver[i])==fa)continue;
int flag=dfs(y,x,col[i],lim[i]);
if((col[i]==1&&lim[i]==1)||(!flag&&lim[i]!=1))continue;
if(res)res=0,ans++;
else res=y;
}
if(!res)return 0;
if(Col && Lim){ans++;return 0;}
return 1;
}
int main(){
freopen("tiger.in","r",stdin);freopen("tiger.out","w",stdout);
int n=read();
for(int i=2,x,y,z;i<=n;i++)x=read(),y=read(),z=read(),add(i,x,y,z),add(x,i,y,z);
int ANS=dfs(1,0,1,1);
printf("%d
",ans);
}
陶陶摘苹果
法一
因为题目中的操作每次都会撤销掉,所以,我们可以预处理出来到每个点时的上升段长度和从每个点开始到最后的上升段长度,用分块处理一下就行了
code
#include<bits/stdc++.h>
#define gc getchar()
#define getch while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=gc;}
#define getnu while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+ch-'0';ch=gc;}
using namespace std;
inline int read(){int s=0,f=1;char ch=gc;getch;getnu;return s*f;}
const int maxn=1e5+10;
int n,m,l,ans,a[maxn],js[maxn],last[maxn],start[maxn],bel[maxn],L[maxn],R[maxn],Max[maxn],cnt;
int find(int l,int val,int id=0){
for(int i=l;i<=R[bel[l]];i++)if(a[i]>val)return i;
for(int i=bel[l]+1;i<=cnt;i++)if(Max[i]>val){id=i;break;}
if(!id)return 0;
for(int i=L[id];i<=R[id];i++)if(a[i]>val)return i;
}
int main(){
freopen("taopapp.in","r",stdin);
freopen("taopapp.out","w",stdout);
n=read(),m=read();
for(int i=1;i<=n;i++)a[i]=read();
int SQRT=sqrt(n);
for(int i=1;i<=n;i++)bel[i]=(i-1)/SQRT+1;
for(int i=1;i<=n;i++){if(bel[i]!=bel[i-1])L[bel[i]]=i;if(bel[i]!=bel[i+1])R[bel[i]]=i;}
cnt=bel[n];
for(int i=1;i<=n;i++)Max[bel[i]]=max(Max[bel[i]],a[i]);
for(int i=1;i<=n;i++){if(a[i]>l)l=a[i],ans++;js[i]=ans,last[i]=l;}
for(int i=n;i>=1;i--){int pos=find(i+1,a[i]);if(!pos)start[i]=1;else start[i]=start[pos]+1;}
while(m--){
int pos=read(),val=read();int tem=a[pos];a[pos]=val;
if(val>last[pos-1]){
int Pos=find(pos+1,a[pos]);
if(!Pos)printf("%d
",js[pos-1]+1);
else printf("%d
",js[pos-1]+start[Pos]+1);
}
else{
int Pos=find(pos,last[pos-1]);
if(!Pos)printf("%d
",js[pos-1]);
else printf("%d
",js[pos-1]+start[Pos]);
}
a[pos]=tem;
}
}
法二
线段树维护单调栈的板子题
code
#include<bits/stdc++.h>
#define gc getchar()
#define getch while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=gc;}
#define getnu while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+ch-'0';ch=gc;}
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid ((l+r)>>1)
using namespace std;
inline int read(){int s=0,f=1;char ch=gc;getch;getnu;return s*f;}
const int maxn=1e5+10;
int tree[maxn<<2],ans[maxn<<2],a[maxn];
int calc(int rt ,int l,int r,int val){
if(l==r)return tree[rt]>val;
if(tree[ls]<=val)return calc(rs,mid+1,r,val);
else return ans[rt]-ans[ls]+calc(ls,l,mid,val);
}
void update(int rt,int l,int r){
tree[rt]=max(tree[ls],tree[rs]);
ans[rt]=ans[ls]+calc(rs,mid+1,r,tree[ls]);
}
void modify(int rt,int l,int r,int pos,int val){
if(l==r)return tree[rt]=val,ans[rt]=1,void();
if(pos<=mid)modify(ls,l,mid,pos,val);
else modify(rs,mid+1,r,pos,val);
update(rt,l,r);
}
int main(){
freopen("taopapp.in","r",stdin);freopen("taopapp.out","w",stdout);
int n=read(),m=read();
for(int i=1;i<=n;i++){a[i]=read();modify(1,1,n,i,a[i]);}
for(int i=1;i<=m;i++){
int pos=read(),x=read();
int tem=a[pos];
modify(1,1,n,pos,x);
printf("%d
",ans[1]);
modify(1,1,n,pos,tem);
}
}
开心的金明
贪心加模拟,考虑每次卖出的电脑的来源,取最优,用set维护一下
code
#include<bits/stdc++.h>
#define int long long
#define gc getchar()
#define getch while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=gc;}
#define getnu while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+ch-'0';ch=gc;}
using namespace std;
inline int read(){int s=0,f=1;char ch=gc;getch;getnu;return s*f;}
const int maxn=5e4+10;
struct node{
int num,fee;
node(){}
node(int _num,int _fee){num=_num,fee=_fee;}
friend bool operator<(node a,node b){return a.fee<b.fee;}
};
multiset<node>S;
int c[maxn],d[maxn],m[maxn],p[maxn],e[maxn],R[maxn],E[maxn];
signed main(){
freopen("happy.in","r",stdin);
freopen("happy.out","w",stdout);
int n=read();
for(int i=1;i<=n;i++)c[i]=read(),d[i]=read(),m[i]=read(),p[i]=read();
for(int i=1;i<n;i++)e[i]=read(),R[i]=read(),E[i]=read();
//c[i]原材料价格
//d[i]需求量
//m[i]做电脑的费用
//p[i]可以生产的数量
//e[i]可储存电脑数量
//R[i]储存原材料的费用
//E[i]储存电脑的费用
int size=0,ans=0,tag=0;
for(int i=1;i<=n;i++){
if(p[i])S.insert(node(p[i],c[i]+m[i]-tag));
size+=p[i];
if(size<d[i])return puts("-1"),0;
int need=d[i];size-=need;
while(need){
node tem=*S.begin();S.erase(S.begin());
if(tem.num>need){
tem.num-=need;ans+=need*(tem.fee+tag);
S.insert(node(tem.num,tem.fee));
need=0;
}else need-=tem.num,ans+=tem.num*(tem.fee+tag);
}
if(i==n)break;
c[i+1]=min(c[i+1],c[i]+R[i]);
if(size>e[i]){
int need=size-e[i];
while(need){
node tem=*--S.end();S.erase(--S.end());
if(tem.num>need){
tem.num-=need;
S.insert(node(tem.num,tem.fee));
need=0;
}else need-=tem.num;
}
size=e[i];
}
tag+=E[i];
}
printf("%lld
",ans);
}
笨小猴
构造题,把所有的卡片按x排序,然后每两个取y大的一个,把最后一个取掉
code
#include<bits/stdc++.h>
#define gc getchar()
#define getch while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=gc;}
#define getnu while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+ch-'0';ch=gc;}
using namespace std;
inline int read(){int s=0,f=1;char ch=gc;getch;getnu;return s*f;}
const int maxn=(1e5+10)*2;
struct node{int x,y,id;}a[maxn];
bool com(node a,node b){return a.x<b.x;}
int main(){
freopen("grandmaster.in","r",stdin);freopen("grandmaster.out","w",stdout);
int n=read()*2+1;
for(int i=1;i<=n;i++)a[i].x=read(),a[i].y=read(),a[i].id=i;sort(a+1,a+n+1,com);
for(int i=1;i<=n;i+=2)if(a[i].y>a[i+1].y)printf("%d
",a[i].id);else printf("%d
",a[i+1].id);
}