10.29 考试

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\n",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\n",*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\n",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);
}
T1treap
#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\n",las);
    }
}
T1正解

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]));
}
T2

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\n",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\n",ans);
}
 
T3

 

posted @ 2017-10-29 21:14  A_LEAF  阅读(188)  评论(0编辑  收藏  举报