首页 > 其他分享 >省选联测9

省选联测9

时间:2023-01-02 19:34:55浏览次数:47  
标签:putchar 省选 ll Re maxn 联测 ans define

序列

一道没有除了分支和循环外任何算法的题 非常适合初学者

1.特殊解出答案 因为合法解都是转动“嵌套”出来的 但是这个结论需要考虑到倒序的方法才能想到

2.发现正序无法确定每个数的位置 但是倒过来用倒序放置每个已放置的数的位置就是固定的 形成一段前后缀

用 \(n\) 个序列一起构造一个特殊解

每次每个排列都放置一个数 每个排列放置的数的个数相等

考虑有几种情况(按优先级来):

1.每个排列对应的前缀长度都相等 后缀长度都相等 那么我们可以直接把里外翻转 所以方案数乘2 前后缀随便放一个即可

2.这个数跟前后缀的下/上一位的位置对应的特殊解处的数一样 直接放

3.如果前后缀上/下一位有空位,放到空位上(因为前后缀上/下一位都有空位其实就是第一种情况,所以我们其实只有一种选择)

4.无解

然后考虑构造 按照贪心应该是先转外层 但是发现每一层都是独立的 顺序其实不影响 先转外层会影响里层区间范围 所以先转里层

Code

#include<iostream>
#define Sakura int
#define Re register ll
#define _ putchar(' ')
#define el putchar('\n')
#define ll long long
#define fre(x,y) freopen(#x".in","r",stdin),freopen(#y".out","w",stdout);

using namespace std;

const ll maxn=1e3+10;
const ll mod=1e9+7;

inline ll read() {
    ll x=0,f=0;char c=getchar();
    while(!isdigit(c)) f|=c=='-',c=getchar();
    while(isdigit(c)) x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return f?-x:x;
}

inline void ot(ll x) {
    if(x<0) putchar('-'),x=-x;
    if(x>9) ot(x/10);putchar(x%10|48);
}

ll T;
ll n,m;
ll a[maxn][maxn],b[maxn];
ll l[maxn],r[maxn];
ll L[maxn],R[maxn],tot;
ll ans;

inline ll qpow(ll x,ll d) {
    ll res=1;
    while(d){
        if(d&1) res=res*x%mod;
        x=x*x%mod;
        d>>=1;
    }
    return res;
}

inline void reverse(ll id){
    ll s=L[id]+R[id];
    for(Re i=L[id];i<s-i;++i) swap(b[i],b[s-i]);
}

inline void solve() {
    n=read(),m=read();
    for(Re i=1;i<=n;++i)
        for(Re j=1;j<=m;++j)
            a[i][j]=read();
    for(Re i=1;i<=n;++i) l[i]=1,r[i]=m;
    for(Re i=1;i<=m;++i) b[i]=0;
    L[1]=1,R[1]=m;
    tot=1;
    ans=0;
    for(Re j=m;j>=1&&ans>=0;--j) {
        for(Re i=1;i<=n;++i){
            if(!b[l[i]]&&!b[r[i]]) {
                ans+=l[i]!=r[i];
                b[l[i]++]=a[i][j];
            }
            else if(b[l[i]]==a[i][j]) ++l[i];
            else if(b[r[i]]==a[i][j]) --r[i];
            else if(!b[r[i]]) b[r[i]--]=a[i][j];
            else if(!b[l[i]]) b[l[i]++]=a[i][j];
            else {
                ans=-1;
                break;
            }
        }
        bool v=true;
        for(Re i=2;i<=n&&v;++i) if(l[i]!=l[i-1]||r[i]!=r[i-1]) v=false;
        if(v) L[++tot]=l[1],R[tot]=r[1];
    }
    ot(ans>=0?qpow(2,ans):0),el;
    if(ans>=0) {
        // for(Re i=1;i<=m;++i) ot(b[i]),_;el;
        // for(Re i=1;i<=tot;++i) ot(L[i]),_,ot(R[i]),el;
        for(Re i=tot;i>=1;--i) 
            if(i<tot&&R[i]==R[i+1]) {
                if(b[L[i]]>b[L[i+1]]) reverse(i+1),reverse(i);
            }
            else if(L[i]<R[i]&&b[L[i]]>b[R[i]]) {
                if(i<tot) reverse(i+1);
                reverse(i);
            }
        for(Re i=1;i<=m;++i) ot(b[i]),_;el;
    }
}

Sakura main(){
    fre(array,array);
    T=read();
    while(T--) solve();
}

序列

是个细节贪心题

先把能选的所有点选上 然后逐个删点

删的话能删大的删大的 因为删了之后可以做边权

然后连一个编号小的父亲 同理

细节麻烦 直接贺的

Code

#include<iostream>
#include<set>
#define Sakura int
#define Re register ll
#define _ putchar(' ')
#define el putchar('\n')
#define ll long long
#define fre(x,y) freopen(#x".in","r",stdin),freopen(#y".out","w",stdout);

using namespace std;

const ll maxn=1e5+10;

inline ll read(){
    ll x=0,f=0;char c=getchar();
    while(!isdigit(c)) f|=c=='-',c=getchar();
    while(isdigit(c)) x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return f?-x:x;
}

inline void ot(ll x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) ot(x/10);putchar(x%10|48);
}

multiset<ll> set1,set2;
ll n;
ll a[maxn],sum[maxn],b[maxn];
ll tot,limit;
ll fa[maxn];
ll ans[maxn];
bool vis[maxn];

Sakura main(){
    fre(tree,tree);
    n=read();
    for(Re i=1;i<=n-1<<1;++i) ++a[read()];
    for(Re i=1;i<=n;++i){
        if(sum[i-1]<i-1) {
            for(Re j=1;j<n;++j) ot(-1),_;
            return 0;
        }
        sum[i]=sum[i-1]+a[i];
    }
    ll last=1;
    for(Re i=2;i<=n;++i) {
        if(sum[i-1]==i-1||i==n) vis[i]=true,++limit;
        if(a[i]||i==n) fa[i]=last,--a[last],++tot,last=i;
    }
    // for(Re i=1;i<=n;++i) ot(fa[i]),ot(vis[i]),_;el;
    ll u=1;
    for(Re i=2;i<n;++i)
        if(!fa[i]) {
            while(!a[u]) ++u;
            --a[u],fa[i]=u;
        }
    ll tmp=tot;
    for(Re i=n-1;i;--i) {
        ll x=min(tmp,a[i]);
        ans[tot]+=x*i;
        a[i]-=x;
        b[i]+=x;    
        tmp-=x;
    }
    // for(Re i=1;i<=n;++i) ot(a[i]),_;el;
    // for(Re i=1;i<=n;++i) ot(b[i]),_;el;
    for(Re i=1;i<n;++i) {
        for(Re j=1;j<=a[i];++j) set1.insert(i);
        for(Re j=1;j<=b[i];++j) set2.insert(i);
    }
    // ot(tot),el;
    // ot(limit),el;
    // ot(ans[tot]),el;
    --tot;
    u=n;
    while(tot>=limit) {
        while(vis[fa[u]]) u=fa[u];
        ll f=fa[u];
        ans[tot]=ans[tot+1];
        for(Re i=0;i<2;++i) {
            ll x=*set2.begin();
            set2.erase(set2.begin());
            set1.insert(x);
            ans[tot]-=x;
        }
        // ot(ans[tot]),el;
        fa[u]=fa[f];
        set1.insert(f);

        ll x=*set1.begin();
        set1.erase(set1.begin());
        fa[f]=x;

        x=*(--set1.end());
        set1.erase(--set1.end());
        set2.insert(x);
        ans[tot]+=x;
        --tot;
    }
    for(Re i=1;i<n;++i) ot(ans[i]?ans[i]:-1),_;
}

集合

6

标签:putchar,省选,ll,Re,maxn,联测,ans,define
From: https://www.cnblogs.com/Sakura-Lu/p/17020386.html

相关文章

  • P8294 [省选联考 2022] 最大权独立集问题
    题解可以发现对于一个子树,假设移出的点为\(u\),移入的点到\(v\),那么这棵子树的根一定是\(LCA(u,v)\).于是可以设\(dp_{u,v}\)表示在以\(LCA(u,v)\)为根的子树......
  • P8290 [省选联考 2022] 填树
    https://www.luogu.com.cn/problem/P8290题解记\(P(l,r)\)表示最小值为\(l\)(至少\(1\)个),其它数在\([l,r]\)的第一问的答案,\(Q(l,r)\)表示最小值为\(l\)(至少\(1\)个)......
  • P8293 [省选联考 2022] 序列变换
    https://www.luogu.com.cn/problem/P8293题解题意转化:将括号序列建成一棵树,操作1相当于把一个点和它的儿子都挂到同一深度的另一个点下面,操作2相当于表示同一深度的......
  • P8292 [省选联考 2022] 卡牌
    https://www.luogu.com.cn/problem/P8292题解先把小于等于\(\sqrt{2000}\)的质数打一个表,发现只有\(14\)个,其中第\(14\)个是\(43\).令前\(14\)个质数为小质数,其它的......
  • 省选11. 字符串
    P3426[POI2005]SZA-Template考虑dp,设\(f(i)\)表示前\(i\)字符所需要的最小印章。\(f(i)\)要么等于\(i\),要么等于\(f(nxt(i))\)。如果存在\(j\geqn-nxt(i)\),......
  • 省选知识点做题记录
    luogu[IOI2014]Wall砖墙题解可以转化为区间取\(min\)和区间取\(max\).规定一下下传标记的顺序推一下式子就行了.[NOIP2013提高组]华容道题解先想到了朴素的......
  • 省选07. 多项式
    P3338[ZJOI2014]力\[\begin{aligned}E_i&=\sum_{j=1}^{i-1}\frac{q_j}{(i-j)^2}-\sum_{j=i+1}^n\frac{q_j}{(i-j)^2}\end{aligned}\]设\(f(x)=q_x\),\(g(x)=x^2\),\(h(......
  • 省选08. 组合计数
    P4091[HEOI2016/TJOI2016]求和有一个重要的通项公式\[\begin{Bmatrix}n\\m\end{Bmatrix}=\sum_{i=0}^{m}\frac{i^n(-1)^{m-i}}{i!(m-i)!}\]\[ans=\sum_{i=0}^{n}\sum......
  • 省选09. 图论
    P2469[SDOI2010]星际竞速可以发现,一个点要么是起点,要么从其它点进入,且每个点最多只会进入一次,出去一次。因此,可以用流量限制每个点被访问一次,用费用计算代价,问题就转化......
  • 省选10. 动态规划
    P3736[HAOI2016]字符合并考虑区间dp+状压dp。设\(dp(l,r,s)\)表示\([l,r]\)合并成\(s\)的最大分数。如果\(r-l+1=len\),那么合并后的长度一定是\(len\bmod{......