T1
考试用treap水过了...我自己造的数据明明跑了12s
(1)Treap
直接0~m个值全都塞进Treap里,然后就是插入和删除了
不要用new,要么重载new,要么开数组...
(2)用队列和单调队列维护
维护一个cnt表示当前0~cnt卡车上都已经加入过(当前0~cnt的值并不一定在卡车上)
如果0~cnt都在卡车上,那么ans=cnt+1
否则,我们需要维护一个红茶编号单调上升的队列记录丢出的红茶
ans=min(队首,cnt+1)
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <iostream> #include <set> #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) #define rint register int #define dd double #define ls(x) ((x)->ch[0]) #define rs(x) ((x)->ch[1]) #define s(x) ((x)->s) #define fix(x) ((x)->fix) #define order(x) ((x)->order) using namespace std; char rea=0; inline void read(int &x) { x=0; while(rea<'0'||rea>'9') rea=getchar(); while(rea>='0'&&rea<='9') x=x*10+rea-'0',rea=getchar(); } const int N=10000006; int m,K; int dui[N+1000000],he,en; struct treap { int s,order,fix; treap *ch[2]; treap(){} treap(int _order,int _s,int _fix) { order=_order; s=_s; fix=_fix; ch[0]=ch[1]=NULL; } treap(int _order,int _s) { order=_order; s=_s; fix=rand(); ch[0]=ch[1]=NULL; } }*null,*root,tong[N*2]; int size; void lturn(treap *&x) { treap *y=rs(x); rs(x)=ls(y); ls(y)=x; x=y; if(x!=null) s(x)=s(ls(x))+s(rs(x))+1; if(y!=null) s(y)=s(ls(y))+s(rs(y))+1; } void rturn(treap *&x) { treap *y=ls(x); ls(x)=rs(y); rs(y)=x; x=y; if(x!=null) s(x)=s(ls(x))+s(rs(x))+1; if(y!=null) s(y)=s(ls(y))+s(rs(y))+1; } treap* kth(int k) { treap *x=root; int tt; while(x!=null) { tt=s(ls(x))+1; if(tt==k) return x; if(tt<k) k-=tt,x=rs(x); else x=ls(x); } return null; } void add(int order,treap *&x) { if(order>m) return ; if(x==null) { tong[size]=treap(order,1);; x=&tong[size++]; ls(x)=rs(x)=null; return ; } if(order<order(x)) { add(order,ls(x)); if(fix(ls(x))<fix(x)) rturn(x); } else { add(order,rs(x)); if(fix(rs(x))<fix(x)) lturn(x); } if(x!=null) s(x)=s(ls(x))+s(rs(x))+1; } void del(int order,treap *&x) { if(order>m) return ; if(order==order(x)) { if(ls(x)!=null&&rs(x)!=null) { if(fix(ls(x))<fix(rs(x))) { rturn(x); del(order,rs(x)); } else { lturn(x); del(order,ls(x)); } } else { if(ls(x)!=null) x=ls(x); else x=rs(x); } } else if(order<order(x)) del(order,ls(x)); else del(order,rs(x)); if(x!=null) s(x)=s(ls(x))+s(rs(x))+1; } treap* build(int l,int r,int hi) { if(l>r) return null; int mid=(l+r)>>1; tong[size]=treap(mid,1,hi); treap *x=&tong[size++]; ls(x)=build(l,mid-1,hi+1); rs(x)=build(mid+1,r,hi+1); return x; } bool ka[N],t[N]; void workbb() { rint i,j; int now=0,op,tin,las=0; for(i=0;i<N;++i) t[i]=1; he=1; en=0; for(i=1;i<=m;++i) { read(op); if(op==1) { read(tin); if(K) tin^=las; ka[tin]=1; t[tin]=0; while(!t[now]) ++now; } else if(op==2) { read(tin); if(K) tin^=las; ka[tin]=0; t[tin]=1; dui[++en]=tin; if(now>tin) now=tin; } else if(op==3) { ka[dui[he]]=1; t[dui[he]]=0; ++he; while(!t[now]) ++now; } else printf("%d ",now); } } set<int> se; void workbao() { rint i; int las=0,op,tin; he=1; en=0; for(i=0;i<=m;++i) se.insert(i); for(i=1;i<=m;++i) { read(op); if(op==1) { read(tin); if(K) tin^=las; if(tin<=m) se.erase(tin); } else if(op==2) { read(tin); if(K) tin^=las; if(tin<=m) se.insert(tin); dui[++en]=tin; } else if(op==3) { if(tin<=m) se.erase(dui[he]); ++he; } else printf("%d ",*se.begin()); } } void work() { rint i; int las=0,op,tin; null=&tong[size++]; root=build(0,m,1); he=1; en=0; for(i=1;i<=m;++i) { read(op); if(op==1) { read(tin); if(K) tin^=las; del(tin,root); } else if(op==2) { read(tin); if(K) tin^=las; add(tin,root); dui[++en]=tin; } else if(op==3) del(dui[he],root),++he; else { las=kth(1)->order; printf("%d ",las); } } } int main(){ //freopen("T1.in","r",stdin); //freopen("T1.out","w",stdout); //freopen("knowledge.in","r",stdin); //freopen("knowledge.out","w",stdout); read(m); read(K); if(m<=1000) workbb(); else if(m<=100000) workbao(); else work(); //fclose(stdin); //fclose(stdout); }
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <iostream> #include <queue> #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) #define rint register int using namespace std; inline void read(int &x) { x=0; char q=getchar(); while(q<'0'||q>'9') q=getchar(); while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar(); } const int N=20000006; int m,K; int cnt=-1; bool flag[N]; int dui[N],he,en; int dui1[N],he1,en1; int main(){ //freopen("in.in","r",stdin); rint i; int op,tin,las=0; he=1; en=0; he1=1; en1=0; read(m); read(K); for(i=1;i<=m;++i) { read(op); if(op==1) { read(tin); if(K) tin^=las; flag[tin]=1; while(flag[cnt+1]) ++cnt; } else if(op==2) { read(tin); if(K) tin^=las; while(en>=he&&dui[en]>=tin) --en; dui[++en]=tin; dui1[++en1]=tin; } else if(op==3) { if(dui[he]==dui1[he1]) ++he; ++he1; } else las=min(cnt+1,(en>=he?dui[he]:0x7fffffff)),printf("%d ",las); } }
T2
感觉好神啊...
CF671D...
$f_x$表示以x为根的子树里的树枝都被覆盖了,并且x到父亲的边也被覆盖了的最小花费
那么考虑每一条链来更新$f_x$
每一条经过x并覆盖x到父亲边的链都可以更新$f_x$
那么这条链的底端点到x周围的儿子节点的f之和 以及 这条链的c 和$f_x$取min
这个就用线段树优化
注意特殊处理1节点
ps.呆毛dp???...
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <iostream> #include <vector> #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) #define rint register int using namespace std; inline void read(int &x) { x=0; char q=getchar(); while(q<'0'||q>'9') q=getchar(); while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar(); } const int N=300006; const ll Inf=1e15; int first[N],ver[N<<1],nt[N<<1],e; inline void addbian(int u,int v) { ver[e]=v; nt[e]=first[u]; first[u]=e++; } int n,m; vector<int> tp[N],dw[N]; int c[N],L[N],R[N],tim,pos[N]; ll f[N]; int fa[N]; void dfs(int x) { int i,sz=dw[x].size(); L[x]=tim+1; for(i=0;i<sz;++i) pos[dw[x][i]]=++tim; for(i=first[x];i!=-1;i=nt[i]) { if(ver[i]==fa[x]) continue; fa[ver[i]]=x; dfs(ver[i]); } R[x]=tim; } ll mn[N<<2],laz[N<<2]; void pushdown(int x) { if(laz[x]) { laz[x<<1]+=laz[x]; laz[x<<1|1]+=laz[x]; mn[x<<1]+=laz[x]; mn[x<<1|1]+=laz[x]; laz[x]=0; } } void build(int l,int r,int x) { mn[x]=Inf; laz[x]=0; if(l==r) return ; int mid=(l+r)>>1; build(l,mid,x<<1); build(mid+1,r,x<<1|1); } void add(int L,int R,ll vv,int l,int r,int x) { if(L>R) return ; if(L<=l&&r<=R) { mn[x]+=vv; laz[x]+=vv; return ; } pushdown(x); int mid=(l+r)>>1; if(L<=mid) add(L,R,vv,l,mid,x<<1); if(mid<R) add(L,R,vv,mid+1,r,x<<1|1); if(mn[x<<1]<mn[x<<1|1]) mn[x]=mn[x<<1]; else mn[x]=mn[x<<1|1]; } void modi(int pos,ll vv,int l,int r,int x) { if(l==r) { mn[x]=vv; return ; } pushdown(x); int mid=(l+r)>>1; if(pos<=mid) modi(pos,vv,l,mid,x<<1); else modi(pos,vv,mid+1,r,x<<1|1); if(mn[x<<1]<mn[x<<1|1]) mn[x]=mn[x<<1]; else mn[x]=mn[x<<1|1]; } void qq(int L,int R,ll &an,int l,int r,int x) { if(L>R) return ; if(L<=l&&r<=R) { if(an>mn[x]) an=mn[x]; return ; } pushdown(x); int mid=(l+r)>>1; if(L<=mid) qq(L,R,an,l,mid,x<<1); if(mid<R) qq(L,R,an,mid+1,r,x<<1|1); } void dp(int x) { f[x]=Inf; ll sum=0; int i,sz; for(i=first[x];i!=-1;i=nt[i]) { if(ver[i]==fa[x]) continue; dp(ver[i]); sum+=f[ver[i]]; if(sum>Inf) sum=Inf; } if(x==1) { f[x]=sum; return ; } sz=dw[x].size(); for(i=0;i<sz;++i) modi(pos[dw[x][i]],sum+c[dw[x][i]],1,m,1); sz=tp[x].size(); for(i=0;i<sz;++i) modi(pos[tp[x][i]],Inf,1,m,1); for(i=first[x];i!=-1;i=nt[i]) if(ver[i]!=fa[x]) add(L[ver[i]],R[ver[i]],sum-f[ver[i]],1,m,1); qq(L[x],R[x],f[x],1,m,1); } int main(){ //freopen("in.in","r",stdin); rint i,j; int tin1,tin2; mem(first,-1); read(n); read(m); for(i=1;i<n;++i) { read(tin1); read(tin2); addbian(tin1,tin2); addbian(tin2,tin1); } for(i=1;i<=m;++i) { read(tin1); read(tin2); read(c[i]); tp[tin2].push_back(i); dw[tin1].push_back(i); } dfs(1); build(1,m,1); dp(1); printf("%lld",(f[1]>=Inf?-1:f[1])); }
T3
留下了一个大坑...
粘个标程吧...
#include<cstdio> #include<algorithm> #define fo(i,a,b) for(i=a;i<=b;i++) using namespace std; typedef long long ll; const int maxn=1000000+10,maxnn=3000+10,mo=1000000007; int f[maxn],a[maxn],b[maxn],L[maxn],R[maxn],s[maxn],fac[maxn]; int g[maxnn*2][maxnn*2][3]; int i,j,k,l,r,t,n,m,ans,tmp,x,now; bool A,B,C; int read(){ int x=0,f=1; char ch=getchar(); while (ch<'0'||ch>'9'){ if (ch=='-') f=-1; ch=getchar(); } while (ch>='0'&&ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } return x*f; } bool cmp(int a,int b){ return a>b; } int qsm(int x,int y){ if (!y) return 1; int t=qsm(x,y/2); t=(ll)t*t%mo; if (y%2) t=(ll)t*x%mo; return t; } void prepare(){ fac[0]=1; fo(i,1,n) fac[i]=(ll)fac[i-1]*i%mo; A=1; fo(i,1,n){ L[i]=read();R[i]=read(); if (i>1&&(L[i]!=L[i-1]||R[i]!=R[i-1])) A=0; } if (A){ int ni=qsm(n+1,mo-2); l=L[1];r=R[1]; fo(i,1,n) a[i]=(l+(ll)(r-l)*i%mo*ni%mo)%mo; } else{ fo(i,1,n) a[i]=L[i]; sort(a+1,a+n+1); } } void n2(){ prepare(); g[0][0][0]=1; fo(i,0,n+k-2) fo(j,0,i){ (g[i+1][j][0]+=g[i][j][0])%=mo;//i+1 put 1 if (i+1<=n) (g[i+1][j+1][0]+=g[i][j][0])%=mo;//i+1 put 0,not x if (i+1>=k){//x may pop if (i+1<=n){ if (i+2-k>=j+1) (g[i+1][j+1][2]+=(ll)g[i][j][1]*b[i-k+2]%mo)%=mo;//i+1 put 0,x pop else (g[i+1][j+1][1]+=g[i][j][1])%=mo;//i+1 put 0,x not pop } if (i+2-k>=j) (g[i+1][j][2]+=(ll)g[i][j][1]*b[i-k+2]%mo)%=mo;//i+1 put 1,x pop else (g[i+1][j][1]+=g[i][j][1])%=mo;//i+1 put 1,x not pop if (i+1<=n){ if (i+2-k>=j+1) (g[i+1][j+1][2]+=(ll)g[i][j][0]*b[i-k+2]%mo)%=mo;//i+1 put 0,is x,x pop else if (i+1<=n) (g[i+1][j+1][1]+=g[i][j][0])%=mo;//i+1 put 0,is x } } else{ if (i+1<=n) (g[i+1][j+1][1]+=g[i][j][0])%=mo;//i+1 put 0,is x if (i+1<=n) (g[i+1][j+1][1]+=g[i][j][1])%=mo;//i+1 put 0 (g[i+1][j][1]+=g[i][j][1])%=mo;//i+1 put 1 } if (i+1>k){ if (i+1<=n) (g[i+1][j+1][2]+=g[i][j][2])%=mo;//i+1 put 0 (g[i+1][j][2]+=g[i][j][2])%=mo;//i+1 put 1 } } fo(x,1,n){ now=g[n+k-1][x][2]; (ans+=(ll)now*fac[x-1]%mo*fac[n-x]%mo*a[x]%mo)%=mo; } ans=(ll)ans*qsm(fac[n],mo-2)%mo; (ans+=mo)%=mo; printf("%d ",ans); } int main(){ //freopen("mouko10.in","r",stdin);freopen("mouko10.out","w",stdout); n=read();k=read(); C=1; fo(i,1,n){ b[i]=read(); if (b[i]!=n-i+1) C=0; } if (!C){ n2(); return 0; } prepare(); //sort(a+1,a+n+1,cmp); reverse(a+1,a+n+1); fo(i,1,n) s[i]=(s[i-1]+a[i])%mo; fo(i,1,k-1) (tmp+=(ll)a[i]*i%mo)%=mo; f[1]=a[1]; fo(i,2,k) f[i]=((ll)f[i-1]*i%mo+(ll)fac[i]*a[i]%mo*i%mo)%mo; fo(i,k+1,n){ f[i]=(ll)f[i-1]*i%mo; (f[i]+=(ll)fac[i-1]*k%mo*a[i]%mo*i%mo)%=mo; (f[i]+=(ll)fac[i-1]*((ll)(i-1+k)*(i-k)/2%mo)%mo*a[i]%mo)%=mo; t=(ll)(tmp+(ll)(s[i-1]-s[k-1])*(k-1)%mo)*fac[i-1]%mo; t=(f[i-1]-t)%mo; (f[i]+=t)%=mo; } ans=f[n]; ans=(ll)ans*qsm(fac[n],mo-2)%mo; (ans+=mo)%=mo; printf("%d ",ans); }