zoukankan      html  css  js  c++  java
  • AT4502 [AGC029C] Lexicographic constraints

    题目链接

    题意分析

    由于这道题的话 答案是单调的 所以我们用二分答案求解

    对于相邻的两个串\(S_i\)以及\(S_{i+1}\)

    如果\(|S_i|\)<\(|S_{i+1}|\) 那么\(S_{i+1}\)就是\(S_i\)后接a

    如果\(|S_i|\)>\(|S_{i+1}|\) 我们考虑先删除\(S_i\)\(|S_i|-|S_{i+1}|\)那一部分 然后把剩下的部分看作一个\(k+1\)进制数 进行+1即可

    当然 如果最后连第一位都进位的话 当前答案显然是不成立的

    由于直接暴力操作太难了 我们考虑用一个单调栈维护 维护所有位置上已经不是1的位置信息

    具体分析见代码

    CODE:

    #include<bits/stdc++.h>
    #define N 200080
    #define INF 2100000000
    using namespace std;
    int n,ans,top;
    int num[N];
    struct Node
    {
    	int nowat,nowhave;
    }sta[N];
    void insert(int len,int now)
    {
    	while(top>0&&sta[top].nowat>len) --top;
    	if(sta[top].nowat==len) sta[top].nowhave++;//如果刚好对应上的话 这一位就+1(比如说b->c)
    	else sta[++top]=(Node){len,1};否则的话 也是+1 不过是a->b
    	if(sta[top].nowhave==now) --top,insert(len-1,now);//当前进位 删去 然后位置向前提一位
    } 
    bool check(int now)
    {
    	sta[top=1]=(Node){0,0};//边界条件
    	for(int i=2;i<=n;++i)
    	if(num[i]<=num[i-1]) insert(num[i],now);
    	return sta[1].nowhave==0;
    }
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i) scanf("%d",&num[i]);
    	int st=0;
    	for(int i=2;i<=n;++i) st+=num[i]>num[i-1];
    	if(st==n-1) {printf("1\n");return 0;}//现特判一下只用一个字符就可以的情况
    	int le=2,ri=n;
    	while(le<=ri)
    	{
    		int mid=(le+ri)>>1;
    		if(check(mid)) ans=mid,ri=mid-1;
    		else le=mid+1;
    	}
    	printf("%d\n",ans);
    	return 0;
    } 
    
  • 相关阅读:
    Git 命令使用小笔记
    一个关于if else容易迷惑的问题
    浏览器与Node环境下的Event Loop
    镜面反射
    Socket通信原理
    Git
    vba工具
    为什么要用prototype
    Oracle 列转换为行, 逗号拼接.
    JS中的phototype
  • 原文地址:https://www.cnblogs.com/tcswuzb/p/14425298.html
Copyright © 2011-2022 走看看