zoukankan      html  css  js  c++  java
  • 整理

    Life and death

    Day1

    模拟赛部分

    T1:下降的出现后,之后都填9,注意前缀0

    const int maxN = 1e5 + 7;
    char s[maxN];
    
    int main() {
    	scanf("%s",s + 1);
    	int n = strlen(s + 1);
    	int now = s[1] - '0';
    	int pos = 1,tmp = 1;
    	for(int i = 2;i <= n;++ i) {
    		int x = s[i] - '0';
    		if(x > now) {now = x;pos = i;}
    		else {if(x < now) break;}
    		if(x == now) tmp = i;
    	}
    	if(tmp == n) {
    		printf("%s",s + 1);
    		return 0;
    	}
    	for(int i = 1;i < pos;++ i) {
    		printf("%c",s[i]); 
    	}
    	if(s[pos] != '1') printf("%c",s[pos] - 1);
    	for(int i = pos + 1;i <= n;++ i) printf("9");
    	return 0;
    }
    

    T2:考虑一个 逆序对 对多少个区间产生贡献。
    即答案为(sum_{a_i < a_j,i > j} a_i * a_j * j * (n - i + 1)\%(10^{12} + 7))
    直接用树状数组维护一下.
    比较特殊的是模数太大会爆int.

    const int mod = 1e12 + 7;
    const int maxN = 4e4 + 7;
    
    int a[maxN] , ans,p[100007],b[maxN],s[maxN];
    
    int query(int x) {
    	int ans = 0;
    	for(;x;x -= x & -x) ans = (ans + p[x]) % mod;
    	return ans;
    }
    
    const int MAX = 1e5;
    
    void add(int x , int val) {
    	for(;x <= MAX;x += x & -x) {
    		p[x] = (p[x] + val) % mod;
    	}
    	return ;
    }
    
    int mul(int a , int b) {
    	int ans = 0;
    	for(int now = a;b;b >>= 1, now = (now + now) % mod) {
    		if(b & 1) ans = (ans + now) % mod;
    	}
    	return ans;
    }
    
    signed main() {
    	freopen("multiplication.in","r",stdin);
    	freopen("multiplication.out","w",stdout);
    	int n = gi();
    	for(int i = 1;i <= n;++ i) s[i] = b[i] = gi();
    	sort(s + 1,s + n + 1);
    	for(int i = 1;i <= n;++ i) a[i] = lower_bound(s + 1,s + n + 1,b[i]) - s;
    	for(int i = 1;i <= n;++ i) {
    		int tmp = query(n) - query(a[i]);
    		tmp %= mod;
    		tmp += mod;
    		tmp %= mod;
    		ans = ans + mul(mul(tmp , (n - i + 1)) , b[i]) % mod;
    		ans %= mod;
    		add(a[i] , b[i] * i);
    	}
    	ans %= mod;
    	ans += mod;
    	ans %= mod;
    	cout << ans;
    	return 0;
    }
    
    

    T3:
    我在考场里的想法:

    把矩阵缩小,二维离散化后,用二维树状数组维护。
    单点加,区间查询。
    然后直接用扫描线求矩阵并。

    学弟tzt没有判断矩阵交,直接判断矩阵并 是否等于 最大的矩形就过了。
    可能老师造数据的时候没有卡掉这一点。

    加入这个矩阵的边时,直接check线段树上的值是否为0就能判交了。
    所以大概A掉的做法应该是两遍扫描线。

    赛后题目讲解:

    gdb调试

    Day2

    模拟赛部分

    T1:大大大大大大模拟

    struct player {
    	char name[16]; int num, score;
    } a[2][5][500100];
    int n, m, t, p, q, turn[2][5], sum[2][5], psum, qsum, num, score, team, pos;
    char sname[16], spos[16];
    bool cmp(player a, player b) {
    	return (a.score == b.score ? a.num < b.num : a.score > b.score);
    }
    int main() {
    	freopen("match.in", "r", stdin);
    	freopen("match.out", "w", stdout);
    	scanf("%d%d%d%d%d", &n, &m, &t, &p, &q);
    	for (int i = 1; i <= n + m; i++) {
    		team = (i <= n ? 0 : 1);
    		scanf("%s %d %s %d", sname, &num, spos, &score);
    		if (spos[0] == 'p' && spos[1] == 'g') pos = 0;
    		if (spos[0] == 's' && spos[1] == 'g') pos = 1;
    		if (spos[0] == 's' && spos[1] == 'f') pos = 2;
    		if (spos[0] == 'p' && spos[1] == 'f') pos = 3;
    		if (spos[0] == 'c') pos = 4;
    		a[team][pos][++sum[team][pos]] = (player) {"", num, score};
    		strcpy(a[team][pos][sum[team][pos]].name, sname);
    	}
    	for (int i = 0; i <= 4; i++) {
    		sort(a[0][i] + 1, a[0][i] + sum[0][i] + 1, cmp);
    		sort(a[1][i] + 1, a[1][i] + sum[1][i] + 1, cmp);
    	}
    	for (int i = 0; i <= 4; i++) turn[0][i] = turn[1][i] = 1;
    	psum = 1, qsum = 1;
    	while (p * psum < t || q * qsum < t) {
    		if (p * psum <= q * qsum) team = 0, psum++; else team = 1, qsum++;
    		int mn = 999, pm; player up, down;
    		for (int i = 0; i <= 4; i++) {
    			int k = turn[team][i], c = a[team][i][k].score - a[team][i][k + 1].score;
    			if (k == sum[team][i]) continue;
    			if (c < mn || (c == mn && a[team][i][k + 1].num < up.num))
    				mn = c, pm = i, up = a[team][i][k + 1], down = a[team][i][k];
    		}
    		turn[team][pm]++;
    		char ct = (team == 0 ? 'A' : 'B');
    		printf("Substitution by %c,No.%d %s is coming up to change No.%d %s.
    ", ct, up.num, up.name, down.num, down.name);
    	}
    	return 0;
    }
    

    T2:挺神的一道题,题目难度偏大。
    考场只想到了80(n(log_2n)^2)暴力做法
    正解是二分+单调性。
    二分在上面累计的格子,然后会发现这个东西其实是单调的。

    #include<bits/stdc++.h>
    #define N 500010
    using namespace std;
    typedef long long ll;
    ll s[N], T;
    int x[N], a[N], n;
    bool check(ll H) {
    	ll nowh = 0, tim = 0;
    	int lc = 0, rc = 0, l = 1, r = n + 1;
    	for (int i = 1; i <= n; i++)
    		if (nowh + a[i] <= H) nowh += a[i], tim += (ll)(x[i] - x[1]) * a[i];
    		else {r = i, rc = H - nowh, tim += (ll)(x[i] - x[1]) * rc; break;}
    	if (tim <= T) return 1;
    	for (int i = 2; i <= n; i++) {
    		ll suml = s[i - 1] - s[l - 1] - lc;
    		ll sumr = s[r - 1] - s[i - 1] + rc;
    		tim += (x[i] - x[i - 1]) * (suml - sumr);
    		while (r <= n && x[i] - x[l] > x[r] - x[i]) {
    			int can = min(a[l] - lc, a[r] - rc);
    			tim += (x[r] - x[i] - x[i] + x[l]) * can;
    			lc += can, rc += can;
    			if (lc >= a[l]) ++l, lc = 0;
    			if (rc >= a[r]) ++r, rc = 0;
    		}
    		if (tim <= T) return 1;
    	}
    	return 0;
    }
    int main() {
    	freopen("block.in", "r", stdin);
    	freopen("block.out", "w", stdout);
    	scanf("%d%I64d", &n, &T); T /= 2;
    	for (int i = 1; i <= n; i++) scanf("%d", &x[i]);
    	for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    	for (int i = 1; i <= n; i++) s[i] = s[i - 1] + a[i];
    	ll l = 0, r = s[n], ans;
    	while (l <= r) {
    		ll mid = (l + r) >> 1;
    		if (check(mid)) l = mid + 1, ans = mid;
    		else r = mid - 1;
    	}
    	printf("%I64d
    ", ans);
    	return 0;
    }
    

    T3:神仙manacher题不会做

    赛后讲解

    CF17E Palisection
    

    首先补集转化。转而计算有多少个回文子串不相交
    首先处理所有以该点为中心的回文子串能扩展到的最大位置。
    然后差分,前缀和。
    再前缀和。
    处理答案即可。

    codeforces 1045B
    

    分析问题的神仙题。
    考虑一个数(z)怎么才能不被表示出来。
    就是对于每一个(a_i)都能找到另外一个(a_j)使得((a_i+a_j) % M = z)
    把序列a从小到大排序
    如果(a_i <= Z),则(a_j)一定(<= M)
    如果(a_i > Z),则(a_j)一定(> M)
    这个是可以证明的。
    然后把序列分成两部分要保证两部分首位相等,即回文。
    这样就可以处理回文串,然后差分加上,最后用前缀和计算答案。

    几个简单的小问题
    

    数轴上有n个开区间((a_i,b_i))。选择尽量多个区间,是的这些区间两两没有公共点。

    把b_i从小到大排序
    一定选择第一个,记录l,不想交能选就选。

    数轴上有n个闭区间([a_i,b_i]),取尽量少的点,使得每个区间至少有一个点。

    按左端点递增顺序排序,如果左端点相同,按右端点递增顺序排序
    记录最右点,不行则新增加一个点。

    给定n个按长度从大到小排序的区间,取若干个区间使得[1,M]能被覆盖,并要使得最短的区间尽量长。
    复杂度要求比(nlogn)

    并查集,依次添加区间,f_i表示i能达到的最右边的点,类似于并查集一样维护起来。
    添加区间的时候,直接开始跳,如果没有被标记,则连起来。

    USACO2005 dec sliver
    

    在n个带权区间中,选择一些区间,覆盖([1,M])所有整数点,求权和的最小值。
    (n le 10^5,mle 10^9)

    按照y_i排序,设(f_i)表示覆盖完全([1,y_i])的权值和的最小值
    (y_j >= x_i)(f_i = min(f_i,f_j + w_i))
    用树状数组维护

    codeforces 776C
    

    一个长度为n的序列,给定数k,求有多少个区间的和是(k^i(i = 0,1,2,3,4,5....))
    (n le 1e5, A_i le 1e5)

    求一个前缀和,问题转化为((sum_i - sum_j) \% k == 0)的方案数
    直接用(f_i)表示sum_j模k -= i的方案数。然后动态更新答案就行了。

    xdoj1079
    

    前缀和水题

    bzoj1044
    

    首先二分长度check出总长度最长的一块最小K.
    然后设(f_{i,j})表示前i个木棍,

    矩阵乘法
    忘记矩阵怎么推的了。
    入门构造题: poj3735 Training little cats

    P3758 [TJOI2017]可乐
    矩阵优化DP
    (f_{i,j})表示走了j步到i的方案数.
    对于操作1(f_{i,j} = f_{i,j - 1})
    对于操作2(f_{i,j} = f_{v,j - 1})
    操作3就是对Ans累加这个和
    然后我们构造一个矩阵来优化快速幂,就是酱紫。
    P3597 [POI2015]WYC
    二分第k小路径的长度,然后用矩阵快速幂计算方案数,check是否>= k
    计算方案数的时候。拆点,对于长度为2的边,多拆出一个点,对于长度为3的边,多拆除两个点

    BZOJ2510 弱题
    

    不会做.

    P2044 [NOI2012]随机数生成器
    

    矩阵优化递推。

    一些奇奇怪怪的NPC问题:

    3-sat
    哈密尔顿路(回路
    三分图
    最大

    博弈论

    如果一个状态只能转移必胜态,那这个是必败态。
    如果一个状态转移出去的有一个是必败态,那么这个状态是必胜态。

    这样就可以设状态DP了.
    题目:
    有两个数x,y = (1,0)。
    每次有三种可能的操作。
    1.(x,y) -> (1,x+y)
    2.(x,y) -> (2x,y)
    3.(x,y) -> (3x,y)
    给定一个数K.
    y >= k.他就输,x + y >= k时,只能使用1操作
    k<=5w.

    首先考虑朴素的就是(f_{i}{j})表示x=i,y = j是必胜态还是怎么滴。
    会发现x只能是(3^x*2^y)所以设(f[i][k][j])表示(x=2^i*3^k y=j)的状态
    SG定理
    有n个游戏,问先手必胜,还是先手必败。
    SG定理:
    必败态的sg值=0
    SG[i] = mex(i能转移到的状态的SG值)
    n个游戏,一起玩的SG值=每个游戏SG值亦或起来的结果.

    经典问题:NIM石子游戏.
    N堆石子,第i堆石子的个数是(a_i),每次可以对任意一堆石子拿走任意多个石子

    两种做法:1.SG定理DP 2.转化为NIM游戏

  • 相关阅读:
    maven创建父子工程
    webservice之jersey简单实用
    EL表达式处理字符串
    oracle不等于1怎么查?
    day_07 搭建Tomcat服务器使用Servlet服务,后端接受前端请求过来的表单数据并使用
    Day_06 流程控制-循环结构-嵌套循环结构的原理解析
    Day05_流程控制02 循环结构
    day_5 流程控制 选择结构的两种常用语句的使用语法
    day_04 运算符详解
    day_03 变量的数据类型详解
  • 原文地址:https://www.cnblogs.com/gaozhuoyuan/p/11788772.html
Copyright © 2011-2022 走看看