• TJOI2014


    匹配

    给出一个(n(nleq80))个点对(n)个点的带权二分图,求所有最大权匹配的交集。

    先求出一个最大权匹配,然后枚举每一条匹配中的边,检验删除该边后是否还能形成最大权匹配。如果能则说明该边不在交集中,否则一定在交集中。

    电源插排

    一个长度为(n(nleq10^9))的插排,初始时是空的。进行(Q(Qleq10^5))次操作,操作有三种:

    • 向整个插排上最大的空区间(相等取最右)的中间(也取右)插上一个插头(x)
    • 询问区间([L,R])中有几个插头。
    • 拔出插头(x)

    用动态开点线段树来做即可。每条线段维护四个值:左起最长空区间的右端点,区间最长空区间的左、右端点,右起最长空区间的左端点。再记录一下插头(x)的位置就可以删除啦。

    拼图

    给出(n(nleq16))块四连通碎片,求有多少种方案将他们一起拼成一个(4 imes4)的正方形。若没有,输出No Solution;只有一种,输出Yes, only one!和这个方案;否则输出Yes, many!

    似乎直接爆搜即可,优化一点可以按块由大到小搜索,再优化可以搞搞状压什么的。

    上升子序列

    给出一个(n(nleq10^5))长度的数列,求该数列有多少个不同的长度至少为(2)的上升子序列,答案对(10^9+7)取模。两个子序列(a,b)被认为不同当且仅当(exists i,a_i eq b_i)

    记录(cnt[i])表示目前以数字(i)为结尾的不同上升子序列有多少个。当做到(a_i)时,(cnt[a_i])变为(1+sum_{i=1}^{a[i]-1}cnt[i])个,额外的(1)表示只有一个数的序列({a_i}),求和表示(a_i)能够接在多少个上升子序列后。要注意(cnt[a_i])变为,而不是加上,因为如果存在(a_{i'}=a_i(i'<i)),那么以(a_{i'})结尾的上升子序列一定出现在以(a_i)结尾的上升子序列中(把原序列中的(a_{i'})换成(a_i))。
    那么我们需要支持单点修改和前缀求和,可以用树状数组解决。

    Alice and Bob

    对于序列({x_n}(nleq10^5)),记(a_i)表示以(x_i)结尾的最长上升子序列长度,(b_i)表示以(x_i)开头的最长下降子序列长度。给出({a_n}),求(sum_{i=1}^nb_i)的最大值。

    若在(a_1..a_{i-1})中有(k)个大于(a_i),那么说明在(x_1..x_{i-1})中,至少有(k)个大于(x_i),至少有(a_i-1)个小于(x_i)

    我没太看懂的题解:现在我们已知了一些大小关系。对于未知的关系,我们默认左边大于右边。构造序列并求(sum_{i=1}^nb_i)即可。

    电影评分

    搞一个电影评分系统,进行(n(nleq10^4))次操作,操作有三种:

    • 发布一部编号为(ID)的电影,有(x(xleq5))个主演({actor_x}),其评分为与其有共同主演的最新电影的评分,若没有则为(0)
    • 查询排名为(x)的电影的编号。排名以评分为第一关键字,发布时间为第二关键字。
    • 将电影(ID)的评分调整为原评分与(x)的平均数。

    题解:将题目中的分数分为整数部分和小数部分,将小数部分写成二进制形式,此时可以使用后缀平衡树维护小数之间的大小关系。将小数部分和整数部分结合即可比较分数的大小关系。没大看懂,也不会后缀平衡树。

    Code

    //匹配
    #include <cstdio>
    #include <cstring>
    #include <queue>
    int const N=300;
    int const INF=0x3F3F3F3F;
    int min(int x,int y) {return x<y?x:y;}
    int n;
    int h[N],cnt;
    struct edge{int u,v,c,w,nxt;} ed[N*N];
    void edAdd(int u,int v,int c,int w)
    {
        cnt++; ed[cnt].u=u,ed[cnt].v=v,ed[cnt].c=c,ed[cnt].w=w,ed[cnt].nxt=h[u],h[u]=cnt;
        cnt++; ed[cnt].u=v,ed[cnt].v=u,ed[cnt].c=0,ed[cnt].w=-w,ed[cnt].nxt=h[v],h[v]=cnt;
    }
    int s,t;
    int dst[N],path[N];
    std::queue<int> Q; bool inQ[N];
    void clear() {for(int i=2;i<=cnt;i++) ed[i].c=i&1?0:ed[i].c+ed[i^1].c;}
    bool SPFA()
    {
        for(int u=s;u<=t;u++) dst[u]=-INF,path[u]=0;
        memset(inQ,false,sizeof inQ);
        dst[s]=0; Q.push(s),inQ[s]=true;
        while(!Q.empty())
        {
            int u=Q.front(); Q.pop(),inQ[u]=false;
            for(int i=h[u];i;i=ed[i].nxt)
            {
                int v=ed[i].v,w=ed[i].w;
                if(ed[i].c&&dst[u]+w>dst[v])
                {
                    dst[v]=dst[u]+w,path[v]=i;
                    if(!inQ[v]) Q.push(v),inQ[v]=true;
                }
            }
        }
        return dst[t]>-INF;
    }
    int maxFl()
    {
        int cost=0;
        while(SPFA())
        {
            int fl=INF;
            for(int i=path[t];i;i=path[ed[i^1].v]) fl=min(fl,ed[i].c);
            for(int i=path[t];i;i=path[ed[i^1].v]) ed[i].c-=fl,ed[i^1].c+=fl;
            cost+=fl*dst[t];
        }
        return cost;
    }
    int cntM,M[N];
    int main()
    {
        freopen("match.in","r",stdin);
        freopen("match.out","w",stdout);
        scanf("%d",&n);
        s=0,t=n+n+1; cnt=1;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++) {int x; scanf("%d",&x); edAdd(i,n+j,1,x);}
        for(int i=1;i<=n;i++) edAdd(s,i,1,0),edAdd(n+i,t,1,0);
        int ans=maxFl(); printf("%d
    ",ans);
        cntM=0;
        for(int u=1;u<=n;u++)
            for(int i=h[u];i;i=ed[i].nxt) if(!ed[i].c&&ed[i].v!=s) M[++cntM]=i;
        for(int k=1;k<=cntM;k++)
        {
            clear(),ed[M[k]].c=0;
            int cost=maxFl();
            ed[M[k]].c=1;
            if(cost<ans) printf("%d %d
    ",ed[M[k]].u,ed[M[k]].v-n);
        }
        return 0;
    }
    
    //电源插排
    #include <cstdio>
    #include <algorithm>
    #include <map>
    using namespace std;
    inline char gc()
    {
        static char now[1<<16],*S,*T;
        if(S==T) {T=(S=now)+fread(now,1,1<<16,stdin); if(S==T) return EOF;}
        return *S++;
    }
    inline int read()
    {
        int x=0; char ch=gc();
        while(ch<'0'||'9'<ch) ch=gc();
        while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
        return x;
    }
    int const Q=1e5+10;
    int n,q; map<int,int> pos;
    #define s sg[s0]
    int rt,sgCnt;
    struct seg{int eptL0,eptR0,eptL,eptR,sum; int Lc,Rc;} sg[40*Q];
    void create(int s0,int L0,int R0) {s.eptL0=s.eptR=R0,s.eptR0=s.eptL=L0,s.sum=0;}
    void update(int s0,int L0,int R0)
    {
        int mid=L0+R0>>1; seg Ls=sg[s.Lc],Rs=sg[s.Rc];
        s.eptL0=Ls.eptL0; if(Ls.eptL0==mid) s.eptL0=Rs.eptL0;
        s.eptR0=Rs.eptR0; if(Rs.eptR0==mid+1) s.eptR0=Ls.eptR0;
        int len1=Ls.eptR-Ls.eptL+1,len2=Rs.eptL0-Ls.eptR0+1,len3=Rs.eptR-Rs.eptL+1;
        int mx=max(len2,max(len1,len3));
        if(len3==mx) s.eptL=Rs.eptL,s.eptR=Rs.eptR;
        else if(len2==mx) s.eptL=Ls.eptR0,s.eptR=Rs.eptL0;
        else if(len1==mx) s.eptL=Ls.eptL,s.eptR=Ls.eptR;
        s.sum=Ls.sum+Rs.sum;
    }
    int L,R;
    void add(int s0,int L0,int R0,int v)
    {
        if(L<=L0&&R0<=R)
        {
            s.sum=v;
            if(v==1) s.eptL0=L0-1,s.eptR0=R0+1,s.eptL=L0+1,s.eptR=L0;
            else s.eptL0=s.eptR0=s.eptL=s.eptR=L0;
            return;
        }
        int mid=L0+R0>>1;
        if(!s.Lc) create(s.Lc=++sgCnt,L0,mid);
        if(!s.Rc) create(s.Rc=++sgCnt,mid+1,R0);
        if(L<=mid) add(s.Lc,L0,mid,v); if(mid<R) add(s.Rc,mid+1,R0,v);
        update(s0,L0,R0);
    }
    int query(int s0,int L0,int R0)
    {
        if(s0==0) return 0;
        if(L<=L0&&R0<=R) return s.sum;
        int mid=L0+R0>>1; int res=0;
        if(L<=mid) res+=query(s.Lc,L0,mid);
        if(mid<R) res+=query(s.Rc,mid+1,R0);
        return res;
    }
    int main()
    {
        freopen("switch.in","r",stdin);
        freopen("switch.out","w",stdout);
        n=read(),q=read();
        create(rt=++sgCnt,1,n);
        for(int i=1;i<=q;i++)
        {
            int k=read();
            if(k==0) {L=read(),R=read(); printf("%d
    ",query(rt,1,n));}
            else
            {   
                L=R=(sg[rt].eptL+sg[rt].eptR-1)/2+1;
                if(pos[k]) L=R=pos[k],add(rt,1,n,0),pos[k]=0;
                else add(rt,1,n,1),pos[k]=L;
            }
        }
        return 0;
    }
    
    //上升子序列
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    int const N=1e5+10;
    int const H=1e9+7;
    int n,a[N]; int n0,map[N];
    int tr[N];
    void add(int x,int v) {while(x<=n0) tr[x]=(tr[x]+v)%H,x+=x&(-x);}
    int sum(int x) {int res=0; while(x) res=(res+tr[x])%H,x-=x&(-x); return res;}
    int pre[N];
    int main()
    {
        freopen("subsequence.in","r",stdin);
        freopen("subsequence.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]),map[i]=a[i];
        sort(map+1,map+n+1); n0=unique(map+1,map+n+1)-(map+1);
        for(int i=1;i<=n;i++) a[i]=lower_bound(map+1,map+n0+1,a[i])-map;
        for(int i=1;i<=n0;i++) pre[i]=0;
        for(int i=1;i<=n;i++)
        {
            int res=sum(a[i]-1)+1;
            add(a[i],res-pre[a[i]]); pre[a[i]]=res;
        }
        printf("%d
    ",sum(n0)-n0);
        return 0;
    }
    
  • 相关阅读:
    Java 破解谷歌翻译api,可以实现程序自动化翻译文章
    如何搭建高可用redis架构?
    架构师带你玩转分布式锁
    Java8内存模型—永久代(PermGen)和元空间(Metaspace)
    【SFA官方翻译】使用 Kubernetes、Spring Boot 2.0 和 Docker 的微服务快速指南
    kafka为什么这么优秀!
    讲道理,为什么分布式一定要有Redis?
    Windows系统内存分析工具的介绍
    colspan width issue
    OpenGL ES3 非常好的系列文章
  • 原文地址:https://www.cnblogs.com/VisJiao/p/8552612.html
Copyright © 2020-2023  润新知