9.22 正睿提高4

目录

  • 2018.9.22 正睿提高5

    • A 数组计数(DP)
    • B 旅行(思路)
    • C 进化(思路 二进制拆分)
    • 考试代码
      • B
      • C

2018.9.22 正睿提高5

时间:3.5h
期望得分:100+80+30
实际得分:100+80+30

比赛链接

T2一直以为类似某道虚树题(SDOI2015)。。到最后只想写暴力(写了暴力也该想到了啊 但是已经在划水了)。

A 数组计数(DP)

题目链接

DP。前缀和优化一下就行了。
刚开始滚动数组又少清空了mmp。。

#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define Mod(x) x>=mod&&(x-=mod)
#define mod 998244353
typedef long long LL;
const int N=1e6+5;

int f[2][N],sum[2][N];

inline int read()
{
    int now=0;register char c=gc();
    for(;!isdigit(c);c=gc());
    for(;isdigit(c);now=now*10+c-'0',c=gc());
    return now;
}

int main()
{
    int n=read(),K=read(),now=1,las=0;
    for(int i=1; i<=n; ++i) f[0][i]=1,sum[0][i]=i;//f[1]
    for(int i=2; i<=K; ++i)
    {
        for(int j=i; j<=n; ++j)
            f[now][j]=sum[las][j>>1];
        sum[las][i-1]=sum[now][i-1]=0;
        for(int j=i; j<=n; ++j)
            sum[now][j]=sum[now][j-1]+f[now][j], Mod(sum[now][j]);
        now=las, las^=1;
    }
    printf("%d\n",f[las][n]);

    return 0;
}

B 旅行(思路)

题目链接

如果当前到了\(i\),那么除了\(1\)到\(a_i\)的边走一次,剩下的\(1\)到\(a_1,a_2,...,a_{i-1}\)的路径不与到\(a_i\)重叠的部分都要走两次。
假设到\(a_i\)还要回到\(1\),那么只需要把所有走过的边计算两次。最后减去\(a_i\)到\(1\)的距离即可(深度)。

//92ms  6616kb
#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 200000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=1e5+7;

int Enum,H[N],nxt[N<<1],to[N<<1],fa[N],dep[N];
bool vis[N];
char IN[MAXIN],*SS=IN,*TT=IN;

inline int read()
{
    int now=0;register char c=gc();
    for(;!isdigit(c);c=gc());
    for(;isdigit(c);now=now*10+c-'0',c=gc());
    return now;
}
inline void AE(int u,int v)
{
    to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
    to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
}
void DFS(int x)
{
    for(int i=H[x],v; i; i=nxt[i])
        if((v=to[i])!=fa[x]) fa[v]=x,dep[v]=dep[x]+1,DFS(v);
}

int main()
{
    int n=read(),q=read();
    for(int i=1; i<n; ++i) AE(read(),read());
    DFS(1), vis[1]=1;
    for(int i=1,a,ans=0; i<=q; ++i)
    {
        a=read();
        for(int x=a; !vis[x]; x=fa[x]) vis[x]=1,ans+=2;
        printf("%d\n",ans-dep[a]);
    }

    return 0;
}

C 进化(思路 二进制拆分)

题目链接

设a为原数组,b为进化一次后的数组,c为进化两次后的数组。
则\(c_i=b_{i-1}\oplus b_{i+1}=a_{i-2}\oplus a_i\oplus a_i\oplus a_{i+2}=a_{i-2}\oplus a_{i+2}\)。
通过打表还可以发现,a进化\(2^d\)次后的数组c,满足\(c_i=a_{i-2^d}\oplus a_{i+2^d}\)。
所以进化\(2^d\)后的数组可以\(O(n)\)求。
对T二进制拆分就行了。(对啊,\(2^a+2^b\)次后的就是\(2^a\)次后的再进化\(2^b\)次)
还有边界的问题。我们可以构造一个环来保证这是正确的:\(0\ a[1\sim n]\ 0\ a[n\sim 1]\)。这样两边的\(a\)是对称的,所以两个\(0\)始终是\(0\)(左边右边相等)。
而且\(a[1\sim n]\)两边都是\(0\),所以最后的\(a[1\sim n]\)就是我们要求的。
当然判左右点的时候根据这个判下下标就好了,不需要建出环来。。

//39ms  720kb
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define pc putchar
//#define gc() getchar()
#define MAXIN 300000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=1e5+5;

bool A[N],B[N];
char IN[MAXIN],*SS=IN,*TT=IN;

inline LL read()
{
    LL now=0;register char c=gc();
    for(;!isdigit(c);c=gc());
    for(;isdigit(c);now=now*10+c-'0',c=gc());
    return now;
}

int main()
{
    LL T=read(); int n=read();
    register char c=gc(); for(;!isdigit(c);c=gc());
    bool *now=A, *las=B;
    now[1]=c-'0';
    for(int i=2; i<=n; ++i) now[i]=gc()-'0';
    int len=2*n+2;
    for(LL d=1; T; T>>=1,d<<=1)
        if(T&1)
        {
            std::swap(now,las);
            for(int i=1; i<=n; ++i)
            {
                int l=i-d%len, r=i+d%len;
                if(l<0) l=-l;//关于0对称啊
                if(l>n) l=len-l;
                if(r>len) r-=len;
                if(r>n) r=len-r;
                now[i]=las[l]^las[r];
            }
        }
    for(int i=1; i<=n; ++i) pc(now[i]+'0');

    return 0;
}

考试代码

B

#include <set>
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define MAXIN 200000
//#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=1e5+7;

int n,q,A[N],dgr[N],Enum,H[N],nxt[N<<1],to[N<<1],fa[N],dep[N],sz[N],son[N],top[N],dfn[N+3],ref[N+3];
LL Ans;
bool vis[N],mark[N];
std::set<int> st;
char IN[MAXIN],*SS=IN,*TT=IN;

inline int read()
{
    int now=0;register char c=gc();
    for(;!isdigit(c);c=gc());
    for(;isdigit(c);now=now*10+c-'0',c=gc());
    return now;
}
inline void AE(int u,int v)
{
    ++dgr[v], to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
    ++dgr[u], to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
}
inline int LCA(int u,int v)
{
    while(top[u]!=top[v]) dep[top[u]]>dep[top[v]]?u=fa[top[u]]:v=fa[top[v]];
    return dep[u]>dep[v]?v:u;
}
inline int Dis(int u,int v)
{
    if(!u||!v) return 0;
    return dep[u]+dep[v]-(dep[LCA(u,v)]<<1);
}
inline bool cmp_dfn(int a,int b)
{
    return dfn[a]<dfn[b];
}
void DFS1(int x)
{
    int mx=0; sz[x]=1;
    for(int i=H[x],v; i; i=nxt[i])
        if((v=to[i])!=fa[x])
        {
            fa[v]=x, dep[v]=dep[x]+1, DFS1(v), sz[x]+=sz[v];
            if(sz[v]>mx) mx=sz[v], son[x]=v;
        }
}
void DFS2(int x,int tp)
{
    static int Index;

    top[x]=tp, ref[dfn[x]=++Index]=x;
    if(son[x])
    {
        DFS2(son[x],tp);
        for(int i=H[x]; i; i=nxt[i])
            if(to[i]!=fa[x]&&to[i]!=son[x]) DFS2(to[i],to[i]);
    }
}
bool Subtask4()
{
    for(int i=2; i<=n; ++i) if(dgr[i]>1) return 0;
    int ans=0;
    if(A[1]!=1) ++ans; printf("%d\n",ans);
    for(int i=2; i<=q; ++i)
    {
        if(A[i]==1) printf("%d\n",ans+1);
        else ans+=2, printf("%d\n",ans);
    }
    return 1;
}
bool DFS3(int x,int s)
{
    bool fl=0;
    for(int i=H[x],v; i; i=nxt[i])
        if((v=to[i])!=fa[x])
            fl|=DFS3(v,(mark[v]?1:2));
    if(fl||vis[x]) Ans+=s;
    return fl||vis[x];
}
void Subtask2()
{
    for(int i=1,ai; i<=q; ++i)
    {
        vis[ai=A[i]]=1;
        for(int p=ai; p!=1; p=fa[p]) mark[p]=1;
        Ans=0, DFS3(1,0), printf("%lld\n",Ans);
        for(int p=ai; p!=1; p=fa[p]) mark[p]=0;
    }
}

int main()
{
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);

    n=read(), q=read();
    for(int i=1; i<n; ++i) AE(read(),read());
    DFS1(1), DFS2(1,1);
    for(int i=1; i<=q; ++i) A[i]=read();
    if(Subtask4()) return 0;
    if(n<=4000) return Subtask2(),0;
//  Subtask2();

    int mx=0;//Chain
    for(int i=1,ai; i<=q; ++i)
    {
        ai=A[i];
        if(dep[ai]>mx) printf("%d\n",mx=dep[ai]);
        else printf("%d\n",mx+mx-dep[ai]);
    }

//  /*st.insert(0),*/ st.insert(N);
//  LL ans=Dis(1,A[1]); printf("%lld\n",ans);
//  st.insert(1); if(A[1]!=1) st.insert(dfn[A[1]]);
//
//  std::set<int>::iterator pre,nxt;
//  for(int i=2,ai,tmp; i<=q; ++i)//不对哎...但是还是能用来过链吧 算了
//  {
//      ai=A[i];
//      int last=ref[*(--st.rbegin())];
//      tmp=Dis(last,ai);
//      printf("%lld\n",ans+tmp);
//
//      if(ai==1) continue;
//
//      pre=st.upper_bound(dfn[ai]), nxt=pre--;
//      if(*nxt==N) ans+=Dis(ai,ref[*pre]);
//      else ans+=Dis(ai,ref[*pre])+Dis(ai,ref[*nxt])-Dis(ref[*pre],ref[*nxt]);
//
//      st.insert(dfn[ai]);
//  }
    return 0;
}/*
10 6
1 2 2 3 1 4 4 6 4 10 4 5 5 7 5 8 5 9
10 1 7 8 3 6

6 5
1 2 2 3 3 4 5 4 6 5
2 5 3 6 1

10 9
1 2 3 2 3 4 4 5 5 6 6 7 7 8 9 8 10 9
7 2 3 1 9 10 4 6 5
*/

C

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define pc putchar
#define gc() getchar()
#define MAXIN 300000
//#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=1e5+5;

bool A[N],B[N];
char IN[MAXIN],*SS=IN,*TT=IN;

inline LL read()
{
    LL now=0;register char c=gc();
    for(;!isdigit(c);c=gc());
    for(;isdigit(c);now=now*10+c-'0',c=gc());
    return now;
}
void Output(bool *a,int n)
{
//  for(int i=1; i<=n; ++i) pc(a[i]+'0'),pc(' '); pc('\n');
    for(int i=1; i<=n; ++i)
    {
        if(a[i]) pc('$');
        else pc('_');
        pc(' ');
    }
    pc('\n');
}
void Subtask1(int T,int n)
{
    for(int i=1; i<=T; ++i)
    {
        B[1]=A[2], B[n]=A[n-1];
        for(int i=2; i<=n; ++i) B[i]=A[i-1]^A[i+1];
        memcpy(A,B,sizeof A);
//      printf("%d:\t",i); Output(A,n);
    }
    for(int i=1; i<=n; ++i) pc(A[i]+'0');
}

int main()
{
//  freopen("my.out","w",stdout);

    LL T=read(); int n=read();
    register char c=gc(); for(;!isdigit(c);c=gc());
    A[1]=c-'0';
    for(int i=2; i<=n; ++i) A[i]=gc()-'0';
    if(T<=1000) return Subtask1(T,n),0;

    return 0;
}/*
100 5
00100

1000 20
11100001110100010101
*/

原文地址:https://www.cnblogs.com/SovietPower/p/9700848.html

时间: 2024-11-05 17:30:33

9.22 正睿提高4的相关文章

正睿提高组2017模拟题二T2

不会线性的,但是群里有个大神,发现用可以用80分的复杂度写出100分的效果,于是.... 考虑每次加入一条边,我们用f[x][j]表示加入第i条边后,当前的并查集x中,第j个点的父亲.那么如何加呢?假设当前第i条边的两端点为u和v,如果第x个并查集中u和v联通那么很明显,它不可以再加到这个并查集中(每个并查集维护的就是一个极大森林),然后就往后找,直到能找到一个x使得其中u和v是不连通的为止(肯定能找到,因为如果已有的都已经连通,说明前x个极大森林中都无法删去这条边,所以再构建一个新的并查集就好

正睿提高组2017模拟题三T1

听了很久又看了很久别人的程序才听懂,于是乎记录一下防止以后忘记. 好啦,假设当前 l-1=5,r=7;那如果学习过树状数组的话就知道题目中的操作如果转换为二进制的话 对于l-1来说他的二进制是101,所以会被加上-1的位置是101和100,r的二进制是111,所以会被加上1的位置是111,110,100 所以可以发现最后更新的位置是l-1的二进制的1的个数+r的二进制的1的个数-2*l-1和r都会更新的位置. 而l-1和r减1都会更新的位置的个数是它们两个二进制的最长公共前缀的1的个数(当然,前

9.1 正睿提高2

目录 2018.9.1 Test A(凸壳 单调栈) B(思路 独立) C 考试代码 A B C 2018.9.1 Test 时间:3.5h 实际得分:40+50+20 比赛链接 T1直接忽略了,刚了3小时T2(暴力写法不好,直接乘逆元就行→_→),算是有点成果吧.. 然后20分钟写完T1.T3.感觉T3也算可做的. A(凸壳 单调栈) 题目链接 注意到\(c_i=0\),即二次函数对称轴都为y轴,但是好像还是很难做.. 但是这样我们可以把一个x提出来,变成\(x(ax+b)\). 所以\(x>

正睿OI国庆DAY2:图论专题

正睿OI国庆DAY2:图论专题 dfs/例题 判断无向图之间是否存在至少三条点不相交的简单路径 一个想法是最大流(后来说可以做,但是是多项式时间做法 旁边GavinZheng神仙在谈最小生成树 陈主力说做法是dfs 首先两个点一定在点双联通分量里 点双是简单环,只有两条,不存在 猜测其他情况存在三条 双联通分量分解 输出情况可以用dfs树判,讨论非树边覆盖情况 内包含 下面分叉连到上面 相交 输出点即可 BFS/例题 BFS树没有跳跃边 计数/动态规划有用吧 树上bfs序好像可以判断距离? 边权

正睿OI DAY3 杂题选讲

正睿OI DAY3 杂题选讲 CodeChef MSTONES n个点,可以构造7条直线使得每个点都在直线上,找到一条直线使得上面的点最多 随机化算法,check到答案的概率为\(1/49\) \(n\leq k^2\) 暴力 \(n\geq k^2\),找点x,求直线l经过x,且点数最多,点数\(\geq k+1\),递归,否则再找一个 One Point Nine Nine 现在平面上有\(n\)个点,已知有一个常数\(D\). 任意两点的距离要么\(\leq D\),要么\(\geq 1.

正睿多校联盟训练Week5

T1 Problem A. 阿瓦的海报输入文件: poster.in输出文件: poster.out时间限制: 1 second空间限制: 512 megabytes阿瓦为了宣传她的影展,准备画一张海报张贴在幻想镇的各个角落.她为了让海报引人注目,已经在图案.背景和排版上费了很大的工夫.但这时她接到一个来自印刷厂的通知:印刷厂的纸不够了,本来答应给阿瓦定做的海报不能达到预期的尺寸.印刷厂表示,剩下的纸最多能够承担每张海报的面积为 S.而阿瓦认为,海报的面积应当是越大越好,所以阿瓦决定,就将每张海

正睿多校联盟训练Week6

并没有参加 Problem A.阿瓦分蛋糕输入文件: cake.in输出文件: cake.out时间限制: 1 second空间限制: 512 megabytes阿瓦为了庆祝自己自己成长为了一只可爱的小猫,决定提前过生日!她觉得,在这一年当中帮助过他最多的就是阿卡和烤乐滋了,于是决定这次只请阿卡和烤乐滋两个人吃蛋糕.阿瓦买了一个 n × m 的蛋糕,她打算分给三个人吃,同时她切蛋糕的时候为了美观,只会在整块的蛋糕上一划到底.也就是说,她如果在蛋糕上切了一刀,那么这一刀的起点和终点一定在蛋糕的边界

[题解向] 正睿Round435

10.14 Link 唔,这一场打得不好.获得了\(\rm 75pts/300pts\)的得分,但是居然可以获得\(\rm 27/69\)的名次,也不至于不满意--毕竟是真不会233 \(\rm T1\) 大概就是字典序那个地方比较爆炸-- 于是就考虑奇数开头和偶数开头分开做,对于每种情况调整成一个合法最小代价序列.这个地方有一个贪心,原来在前面的依旧会在前面,在后面的也还会在后面,扫一遍就做完了. 这个贪心里面蕴含着一个性质.\(now_i<i,now_j<j\),即"同向换&qu

[题解向] 正睿Round409

\(\rm Link\) 然而泥萌没有权限是看不了题目的233. \(\rm T1\) 大概就是个map,脑残出题人认为(x,x)不属于有序二元组,我可qtmd.于是只拿了\(\rm 60pts\) int main(){ ios_base :: sync_with_stdio(false) ; cin.tie(0), cout.tie(0) ; cin >> N >> P ; int i ; for (i = 1 ; i <= N ; ++ i) cin >>