• Codeforces Round #775 (Div. 1)


    CF1648A Weird Sum

    先算横向距离,再算纵向距离。

    const int MAXN = 1e5 + 5;
     
    vector <int> row[MAXN];
    vector <int> col[MAXN];
     
    map <int , int> M;
     
    int n , m , num;
     
    int main() {
    	read(n),read(m);
    	for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) {
    		int c;read(c);
    		if(!M[c]) M[c] = ++num;
    		row[M[c]].push_back(i);
    		col[M[c]].push_back(j);
    	}
    	
    	LL ans = 0;
    	for (int i = 1; i <= num; ++i) {
    		sort(row[i].begin() , row[i].end());
    		for (int j = 0; j < (int)row[i].size() - 1; ++j) {
    			ans += (LL)(j + 1) * (row[i].size() - 1 - j) * (row[i][j + 1] - row[i][j]);
    		}
    		
    		sort(col[i].begin() , col[i].end());
    		for (int j = 0; j < (int)col[i].size() - 1; ++j) {
    			ans += (LL)(j + 1) * (col[i].size() - 1 - j) * (col[i][j + 1] - col[i][j]);
    		}
    	}
    	
    	write(ans);
    	return 0;
    }
    

    CF1648B Integral Array

    调和级数复杂度枚举哪些数作为结果,然后标记可行数。

    const int MAXN = 1e6 + 5;
     
    LL a[MAXN] , num[MAXN] , n , c;
     
    int main() {
    	int T;
    	read(T);
    	while(T -- > 0) {
    		read(n),read(c);
    		for (int i = 1; i <= n; ++i) read(a[i]);
    		sort(a + 1 , a + 1 + n);
    		n = unique(a + 1 , a + 1 + n) - a - 1;
    		for (int i = 1; i <= n; ++i) {
    			for (int j = 1; j <= n && a[i] * a[j] <= c; ++j) {
    				num[a[j] * a[i]] ++;
    				num[min(c + 1 , (a[j] + 1) * a[i])] --;
    			}
    		}
    		for (int i = 1; i <= c; ++i) num[i] += num[i - 1];
    		int fl = 1;
    		for (int i = 1; i <= n; ++i) if(num[a[i]] != i) {
    			fl = 0;
    			break;
    		}
    		if(fl) puts("Yes");
    		else puts("No");
    		for (int i = 1; i <= c + 1; ++i) num[i] = 0;
    	}
    	return 0;
    }
    

    CF1648C Tyler and Strings

    简单推一下维护一下就行。不记得题目了,但记得因为忘记对 ans+1 取模而 fst 。

    const int MAXN = 2e5 + 5;
    const int V = 2e5;
    const int mod = 998244353;
     
    int n , m , num[MAXN];
    int s[MAXN] , t[MAXN];
    LL fac[MAXN] , finv[MAXN] , tr1[MAXN << 2] , tr2[MAXN << 2];
     
    void build(int l , int r , int now) {
    	if(l == r) {
    		tr1[now] = finv[num[l]];
    		tr2[now] = num[l];
    		return;
    	}
    	int mid = (l + r) >> 1;
    	build(l , mid , now << 1);
    	build(mid + 1 , r , now << 1 | 1);
    	tr2[now] = (tr2[now << 1] + tr2[now << 1 | 1]) % mod;
    	tr1[now] = (tr1[now << 1] * tr1[now << 1 | 1]) % mod;
    }
     
    void update(int l , int r , int now , int x) {
    	if(l == r) {
    		tr1[now] = tr1[now] * tr2[now] % mod;
    		tr2[now] = tr2[now] - 1;
    		return;
    	}
    	int mid = (l + r) >> 1;
    	if(x <= mid) update(l , mid , now << 1 , x);
    	else update(mid + 1 , r , now << 1 | 1 , x);
    	tr2[now] = (tr2[now << 1] + tr2[now << 1 | 1]) % mod;
    	tr1[now] = (tr1[now << 1] * tr1[now << 1 | 1]) % mod;
    }
     
    LL find(int l , int r , int now , int x , int y) {
    	if(l >= x && r <= y) {
    		return tr2[now];
    	}
    	int mid = (l + r) >> 1;
    	LL res = 0;
    	if(x <= mid) res = (res + find(l , mid , now << 1 , x , y)) % mod;
    	if(y > mid) res = (res + find(mid + 1 , r , now << 1 | 1 , x , y)) % mod;
    	return res;
    }
     
    LL qpow(LL a , LL b) {
    	LL res = 1;
    	while(b) {
    		if(b & 1) res = res * a % mod;
    		a = a * a % mod;
    		b >>= 1;
    	}
    	return res;
    }
     
    int main() {
    	read(n),read(m);
    	for (int i = 1; i <= n; ++i) read(s[i]) , num[s[i]] ++;
    	for (int i = 1; i <= m; ++i) read(t[i]);
    	
    	fac[0] = 1;
    	for (int i = 1; i <= V; ++i) fac[i] = fac[i - 1] * i % mod;
    	finv[V] = qpow(fac[V] , mod - 2);
    	for (int i = V; i >= 1; --i) finv[i - 1] = finv[i] * i % mod; 
    	
    	build(1 , V , 1);
    	
    	LL ans = 0;
    	for (int i = 0; i < m && i <= n; ++i) {
    		if(i) {
    			if(!num[t[i]]) break;
    			num[t[i]] --;
    			if(i == n) {
    				ans ++;
    				ans %= mod;
    				break;
    			}
    			update(1 , V , 1 , t[i]);
    		}
    		LL res1 = 1 , res2 = 0;
    		if(t[i + 1] != 1) res2 = find(1 , V , 1 , 1 , t[i + 1] - 1);
    		res1 = tr1[1];
    		ans = (ans + fac[n - i - 1] * res1 % mod * res2 % mod) % mod;
    	} 
    	write(ans);
    	return 0;
    }
    

    CF1648D Serious Business

    由于只能往下走或往右走,那么在走到第三层时决策固定。

    因此我们只考虑什么时候从第一层和第二层下来。

    定义 \(f_i\) 表示在 \((2,i)\) 时停下的最大权值。

    我们枚举我们选择的最后一个操作,设他为 \((l,r,k)\)

    那么对于所有 \(i \in [l,r]\) 会有两种转移方式。

    一种是 \(f_i = \max(f_i , f_{l-1}+suf_{2,l}-suf_{2,i+1})\)

    另一种是 \(f_{i} = \max(f_{i} , pre_{1,j}+suf_{2,j}-suf_{2,i+1}) , j \in [l,i]\)

    容易发现 \(-suf_{2,i+1}\) 是常数,可以最后解决。

    对于第一种,我们把操作按左端点排序,则可以保证在进行后面的操作时,所有 \(f_{i},i \in [1,l)\) 已经被计算,然后线段树区间取最大值。

    对于第二种,在线段树上维护一个左子树对右子树贡献的标记,就可以维护。

    可惜考场没写完,大概是省选签到级别?

    #include <map>
    #include <set>
    #include <queue>
    #include <cmath>
    #include <bitset>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define pii pair <int , int>
    #define pll pair <LL , LL>
    #define mp make_pair
    #define fs first
    #define sc second
    #define int long long
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    
    //const int Mxdt=100000; 
    //static char buf[Mxdt],*p1=buf,*p2=buf;
    //#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,Mxdt,stdin),p1==p2)?EOF:*p1++;
    
    template <typename T>
    void read(T &x) {
    	T f=1;x=0;char s=getchar();
    	while(s<'0'||s>'9') {if(s=='-') f=-1;s=getchar();}
    	while(s>='0'&&s<='9') {x=(x<<3)+(x<<1)+(s-'0');s=getchar();}
    	x *= f;
    }
    
    template <typename T>
    void write(T x , char s='\n') {
    	if(!x) {putchar('0');putchar(s);return;}
    	if(x<0) {putchar('-');x=-x;}
    	T tmp[25]={},t=0;
    	while(x) tmp[t++]=x%10,x/=10;
    	while(t-->0) putchar(tmp[t]+'0');
    	putchar(s); 
    }
    
    const int MAXN = 5e5 + 5;
    const LL inf = 1e18;
    
    LL tr[MAXN << 2] , Max[MAXN << 2] , tag[MAXN << 2];
    LL pre1[MAXN] , suf2[MAXN] , suf3[MAXN] , n , Q;
    LL a[5][MAXN];
    
    void build(int l , int r , int now) {
    	tr[now] = -inf;tag[now] = inf;
    	if(l == r) {
    		Max[now] = pre1[l] + suf2[l];
    		return;
    	}
    	int mid = (l + r) >> 1;
    	build(l , mid , now << 1);
    	build(mid + 1 , r , now << 1 | 1);
    	Max[now] = max(Max[now << 1] , Max[now << 1 | 1]);
    }
    
    void push_down(int now) {
    	if(tag[now] != inf) {
    		tr[now << 1 | 1] = max(Max[now << 1] - tag[now] , tr[now << 1 | 1]);
    		tag[now << 1] = min(tag[now << 1] , tag[now]);
    		tag[now << 1 | 1] = min(tag[now << 1 | 1] , tag[now]);
    	}
    }
    
    void update(int l , int r , int now , int x , int y , LL val) {
    	if(l >= x && r <= y) {
    		tr[now] = max(tr[now] , val);
    		return;
    	}
    	push_down(now);
    	int mid = (l + r) >> 1;
    	if(x <= mid) update(l , mid , now << 1 , x , y , val);
    	if(y > mid) update(mid + 1 , r , now << 1 | 1 , x , y , val);
    }
    
    void modify(int l , int r , int now , int x , int y , LL k , LL &cur) {
    	if(l >= x && r <= y) {
    		tr[now] = max(tr[now] , cur - k);
    		tag[now] = min(tag[now] , k);
    		cur = max(cur , Max[now]);
    		return;
    	}
    	int mid = (l + r) >> 1;
    	push_down(now);
    	if(x <= mid) modify(l , mid , now << 1 , x , y , k , cur);
    	if(y > mid) modify(mid + 1 , r , now << 1 | 1 , x , y , k , cur);
    }
    
    LL find(int l , int r , int now , int x) {
    	if(l == r) return max(tr[now] , Max[now] - tag[now]);
    	LL res = tr[now];
    	push_down(now);
    	int mid = (l + r) >> 1;
    	if(x <= mid) res = max(res , find(l , mid , now << 1 , x));
    	else res = max(res , find(mid + 1 , r , now << 1 | 1 , x));
    	return res;
    }
    
    vector <pii> G[MAXN];
    LL f[MAXN];
    
    signed main() {
    	read(n),read(Q);
    	for (int i = 1; i <= n; ++i) read(a[1][i]) , pre1[i] = pre1[i - 1] + a[1][i];
    	for (int i = 1; i <= n; ++i) read(a[2][i]);
    	for (int i = n; i >= 1; --i) suf2[i] = suf2[i + 1] + a[2][i];
    	for (int i = 1; i <= n; ++i) read(a[3][i]);
    	for (int i = n; i >= 1; --i) suf3[i] = suf3[i + 1] + a[3][i];
    	
    	build(1 , n , 1);
    	
    	for (int i = 1; i <= Q; ++i) {
    		int l , r , k;
    		read(l),read(r),read(k);
    		G[l].push_back(mp(r , k));
    	}
    	
    	int now = 0;
    	f[0] = -inf;
    	
    	LL ans = -inf;
    	
    	for (int i = 1; i <= n; ++i) {
    		while(now + 1 < i) now ++ , f[now] = find(1 , n , 1 , now) , f[now] -= suf2[now + 1] , ans = max(ans , f[now] + suf3[now]);
    		for (int j = 0; j < (int)G[i].size(); ++j) {
    			LL r = G[i][j].fs , k = G[i][j].sc;
    			update(1 , n , 1 , i , r , f[i - 1] + suf2[i] - k);
    			LL cur = -inf;
    			modify(1 , n , 1 , i , r , k , cur);
    		}
    	}
    	while(now + 1 <= n) now ++ , f[now] = find(1 , n , 1 , now) , f[now] -= suf2[now + 1] , ans = max(ans , f[now] + suf3[now]);
    	
    	write(ans);
    	
    	return 0;
    }
    
  • 相关阅读:
    iscsi-分区类型
    NFS
    测试目录
    测试
    函数
    循环、枚举、条件判断、选择排序
    格式化、列表、元组、字典、集合
    常量、注释、变量、堆栈、数据类型、强制转换
    站点迁移至https://traceless.site/
    CENTOS7 源码安装NGINX
  • 原文地址:https://www.cnblogs.com/Reanap/p/16079698.html
Copyright © 2020-2023  润新知