200天1000题 (DAY 2)

200天1000题 (DAY 2)

目前总题数: 7

目前CF分数: 1325

T1 (CF #791 DIV.2)B. Stone Age Problem

/*
	题目大意:
		给你一个长度为n的数组a
		将要对他进行q次操作
		
		每轮操作
		有1/2两种选择
		1表示接下来输入 p和x  把第p个点修改为x并且输出当前数组的总和
		2表示接下来输入 x  把a中所有元素修改为x并且输出当前数组的总和
*/

/*
	题目的数据范围是 n,q都是2e5以内
	ai是1e9,因此直接暴力做会T
	
	这个题有一个关键的点就是我们只关心当前状态下的总和,不关心每个点在每一轮操作的具体情况
	
	因此我们可以引入一种延迟操作
	定义一个变量 aver 表示上一次全局修改的操作版本
	定义一个数组 ver[],ver[i]表示第i个元素当前的版本是多少
	假设我们要对 i 元素单独修改,那么我们可以检查他的版本号和全局的版本号对比
	如果全局的版本号比他大那就意味着他现在的值应该是上一次全局修改的值
	
	具体实现看代码。
*/



const int N = 1e6 + 10;

int n,q;
int sumn = 0; // 总和,也就是答案
int aver = 0; // 全局版本
int alls = 0; // 上一次全局修改的值

inline void sensei()
{
    
    cin >> n >> q;
    vector<int> a(n+1);
    vector<int> ver(n+1);
    
    for(int i=1;i<=n;i++){
        cin >> a[i];
        sumn += a[i];
        ver[i] = 0;
    }
    
    while(q -- ){
        int op;
        cin >> op ;
        if(op == 1){
            // 单点变换
            int pos,x;
            cin >> pos >> x;
            // 判断版本号
            if(ver[pos] < aver){
                // 当前版本号低于上次全局修改的
                ver[pos] = aver;
                a[pos] = x;
                sumn += (x - alls);
            }else{
                sumn += (x - a[pos]);
                a[pos] = x;
            }
        }else{
            // 区间变换
            aver++;
            int p;
            cin >> p;
            alls = p;
            sumn = alls*n;
        }
        cout << sumn << endl;
    }
    
}

signed main()
{
    fuckios
    sensei();
    return 0;
}

T2 (CF Edu #127 DIV.2)C.Dolce Vita


const int N = 1e6 + 10;



inline void sensei()
{
    int n,x;
    cin >> n >> x;
    vector<int> a(n+1);
    for(int i=1;i<=n;i++){
        cin >> a[i];
    }
    sort(a.begin()+1,a.begin()+1+n);
    vector<int> pre(n+1);
    for(int i=1;i<=n;i++){
        pre[i] = pre[i-1] + a[i];
    }
    int ans = 0;
    int k = 0;
    for(int i=n;i>=1;i--){
        if(pre[i] + k*i > x) continue;
        int alls = (x-pre[i]-k*i)/i+1;
        ans+=alls*i;
        k+=alls;
    }
    cout << ans << endl;
}

signed main()
{
    fuckios
    int t;
    
    cin >>t ;
    while(t --){
        sensei();
    }
    return 0;
}

T3: (CF EDU #125 DIV.2)C. Bracket Sequence Deletion

const int N = 1e6 + 10;


signed main()
{
    fuckios
    int T; cin >> T;
    while (T--)
    {
        int n; cin >> n;
        string s; cin >> s;
        
        int i = 0, k = 0;
        while (i < n - 1)
        {
            if (s[i] == '(')
            {
                i += 2;
                k++;
            }
            else
            {
                int j = i + 1;
                while (j < n && s[j] != ')')
                    j++;
                if (j == n) break;//注意:如果没有找到')',应当break掉
                k++;
                i = j + 1;
            }
        }
        
        cout << k << " " << n - i << endl;
    }
    
    return 0;
}

T4 (ABC #242) B.Minimize Ordering

// 非常水 

signed main()
{
    string s;
    cin >> s;
    sort(s.begin(),s.end());
    cout << s << endl;
    return 0;
}

T5 (ABC #242) C - 1111gal password

image-20220914141951727

/*
	定义一个数组 f[i][j]
	表示 位数为i并且首字符为j的的方案数
	
	例如 : 对于 4????? 可以表示为 f[6][4]
	而 4????? 显然等于 43???? + 44???? + 45????  的方案数
	因此状态转移方程是:
		f[i][j] = (f[i-1][j-1] + f[i-1][j] + f[i-1][j+1])%998244353;
	注意边界,j的范围是1~9
	所以要特判 1和9
	
	代码如下:
	
*/

const int N = 1e6 + 10;

const int p = 998244353;

int f[N][10];

inline void sensei()
{
    int k;
    cin >> k;
    
    for(int i=1;i<=9;i++){
        f[1][i] = 1;
    }
    
    int ans = 0;
    
    for(int i=2;i<=k;i++){
        for(int j=1;j<=9;j++){
            if(j == 1){
                f[i][j] = (f[i-1][j] + f[i-1][j+1])%p;        
            }else if(j == 9){
                f[i][j] = (f[i-1][j] + f[i-1][j-1])%p;
            }else{
                f[i][j] = (f[i-1][j]+f[i-1][j+1]+f[i-1][j-1])%p;                
            }
        }
    }
    
    for(int i=1;i<=9;i++){
        ans = (ans+f[k][i])%p;
    }
    cout << ans << endl;
}

signed main()
{
    sensei();
    return 0;
}

T6. (CF #809) C. Qpwoeirut And The City

/*
	题目大意:
		给你一个数组a,长度为n
		当且仅当 a[i]>a[i-1] && a[i]>a[i+1] 时,ai被称作cool的建筑物,你可以给某个建筑物i的高度ai+1(一次操作)
		问如果要让cool的建筑物的数量取得最大
		并且操作数尽量少,那么这个操作数是多少?
*/

/*
题解:
	贪心思路
	当n是奇数那么可以直接求
	当n是偶数就要考虑哪个位置中间可以隔开两个(当然也可以全都是只隔开一个的)
	
	代码的实现很妙
*/

const int N = 1e5 + 10;

int a[N];

inline ll calc(int p)
{
	return max(0ll, 1 + max(a[p + 1], a[p - 1]) - a[p]);
}

inline void sensei()
{
	int n;
	cin >> n ;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}

	int ans = 0;

	if (n & 1) {
		for (int i = 2; i < n; i += 2) {
			ans += calc(i);
		}
		cout << ans << endl;
		return ;
	}

	int alls = 0;
	for (int i = 2; i < n; i += 2) {
		alls += calc(i);
	}
	ans = alls ;
	for (int i = n - 1; i > 1; i -= 2) {
        alls -= calc(i-1);
        alls += calc(i);
        ans = min(ans,alls);
    	debug(alls);
        debug(ans);
    }
    
    cout << ans << endl;
}

signed main()
{
    fuckios
	int t;
	cin >> t;
	while (t --) {
		sensei();
	}
	return 0;
}
posted @ 2022-09-14 22:59  coolJazz  阅读(15)  评论(0)    收藏  举报