Educational Codeforces Round 80 D E

A了三题,rk1000左右应该可以上分啦,开??。

后面的D,E比赛时就感觉可做,但又想不到方法。

然后我补了下,确实如此。

D - Minimax Problem

题意:很简单,给一个矩阵,找两行序列i,j,使得通过每个元素取当列最大合成出来的序列,最小值最大。

hit 1:比赛里我是真的有想二分,最小值最大,这不是经典二分答案套路嘛。

hit 2:比赛里我也是真的有注意到这个m <=8 给的很小,想以此为突破点干点啥?

然后要么太晚了,要么我做了三题自满了,总之没想到最终解法就睡觉了。

其实把二者结合起来,就可以A了这题了。一定注意 如果给的某个数字很小的话,可以二进制转化 。

也就是bitmask,英文好帅。

然后就二分答案,check的时候,对每个序列按是否大于等于你目标值转化成一个二进制串,再找有没有另一个二进制串满足两者通过 按位或  |   起来 得到一个完整的全部满足的全为1的串。

就没了。

贴个代码

 1 #include <bits/stdc++.h>
 2 #ifndef ONLINE_JUDGE
 3 #define debug(x) cout << #x << ": " << x << endl
 4 #else
 5 #define debug(x)
 6 #endif
 7 using namespace std;
 8 typedef long long ll;
 9 const int MAXN=3e5+7;
10 const int INF=0x3f3f3f3f;
11 const int MOD=1e9+7;
12
13 int a[MAXN][10],vis[300];
14 int ans1,ans2,n,m;
15
16 bool check(int x)
17 {
18     for(int i=0;i<(1<<m);++i) vis[i]=0;
19     for(int i=1;i<=n;++i)
20     {
21         int k=0;
22         for(int j=0;j<m;++j)
23         {
24             k+=(a[i][j]>=x)*(1<<j);
25         }
26         vis[k]=i;
27     }
28     for(int i=0;i<(1<<m);++i)
29     {
30         if(!vis[i]) continue;
31         for(int j=0;j<(1<<m);++j)
32         {
33             if(!vis[j]) continue;
34             if((i|j)==(1<<m)-1)
35             {
36                 ans1=vis[i],ans2=vis[j];
37                 return true;
38             }
39         }
40     }
41     return false;
42 }
43
44 int main()
45 {
46     ios::sync_with_stdio(false);
47     cin.tie(0);
48     cin>>n>>m;
49     for(int i=1;i<=n;++i)
50         for(int j=0;j<m;++j)
51             cin>>a[i][j];
52     int l=0,r=INF;
53     while(l<=r)
54     {
55         int mid=l+r>>1;
56         if(check(mid)) l=mid+1;
57         else r=mid-1;
58     }
59     cout<<ans1<<‘ ‘<<ans2<<endl;
60     return 0;
61 }

E - Messenger Simulator

题意:也非常的清晰明了,感觉以前在CF上也见过类似的,不过比这题简单的。就打电话,谁打了就把这个数提到前面。求每个数出现的最小和最大位置。

比赛时,我D想不出,看了眼E,真的有想树状数组维护,但主要我不知道咋移,啥时候哪个位置+1,-1。

然后发现看别人的程序基本就是正解。所以自己算法的思想大致还是到位的,但细部想不出呀。

这题思维的闪光点,主要就是开始时每个元素目前所在pos的设置,设置为i+m,就是预留了m个位置,给询问序列中的m个元素来移动,给开始n个元素的位置设置成虚点!

反正我第一次做是想不到。

别的都很好想,就是对每个询问,也就是给出的序列中给的值,动态的更新位置,并更新最大值,注意新位置应该是从m开始往前,也就是m~1。

树状数组的ask就是询问前缀和,也就是该元素当前处于第几个,也就是他的位置。

贴个代码

 1 #include <bits/stdc++.h>
 2 #ifndef ONLINE_JUDGE
 3 #define debug(x) cout << #x << ": " << x << endl
 4 #else
 5 #define debug(x)
 6 #endif
 7 using namespace std;
 8 typedef long long ll;
 9 const int MAXN=6e5+7;
10 const int INF=0x3f3f3f3f;
11 const int MOD=1e9+7;
12
13 int ans1[MAXN],ans2[MAXN],a[MAXN],pos[MAXN],sum[MAXN];
14 int n,m;
15
16 int lowbit(int x) {return x&(-x);}
17
18 void add(int x,int val)
19 {
20     while(x<MAXN)
21     {
22         sum[x]+=val;
23         x+=lowbit(x);
24     }
25 }
26
27 int ask(int x)
28 {
29     int res=0;
30     while(x)
31     {
32         res+=sum[x];
33         x-=lowbit(x);
34     }
35     return res;
36 }
37
38 int main()
39 {
40     ios::sync_with_stdio(false);
41     cin.tie(0);
42     cin>>n>>m;
43     for(int i=1;i<=n;++i)
44     {
45         ans1[i]=ans2[i]=i;
46         pos[i]=i+m;
47     }
48     for(int i=0;i<m;++i)
49     {
50         cin>>a[i];
51         ans1[a[i]]=1;
52     }
53     for(int i=1;i<=n;++i)
54         add(pos[i],1);
55     for(int i=0;i<m;++i)
56     {
57         int p=a[i];
58         ans2[p]=max(ans2[p],ask(pos[p]));
59         add(pos[p],-1);
60         pos[p]=m-i;
61         add(pos[p],1);
62     }
63     for(int i=1;i<=n;++i)
64         ans2[i]=max(ans2[i],ask(pos[i]));
65     for(int i=1;i<=n;++i)
66         cout<<ans1[i]<<‘ ‘<<ans2[i]<<‘\n‘;
67     return 0;
68 }

原文地址:https://www.cnblogs.com/Zzqf/p/12196001.html

时间: 2024-07-31 22:02:24

Educational Codeforces Round 80 D E的相关文章

Educational Codeforces Round 80 (Rated for Div. 2)

\[Educational\ Codeforces\ Round\ 80\ (Rated\ for\ Div.\ 2)\] A.Deadline 打勾函数找最小值,在\(\sqrt{d}\)邻域里找\(x\)最小化\(x+\lceil\frac{d}{x+1}\rceil\)即可 //#pragma comment(linker, "/STACK:1024000000,1024000000") #include<bits/stdc++.h> using namespace

Educational Codeforces Round 80 (Rated for Div. 2)(C - Two Arrays )

C - Two Arrays 题目链接:https://codeforces.com/contest/1288/problem/C 题目: 题意:给你n,m,利用1~n之间的数(可重复)来组成长度为m的数组a,b,要求数组a非递减,数组b非递增,且a数组的数<=b数组中的数,求出a,b数组对数 思路:用动态规划,dp[i][j]是第i个位置放数字j的方案数,根据题意可以将b数组反置然后接在a后面,则该数组长度为2m,为一个非递减序列,则就是求1~n这些数字可重复组成多少种长度为2m的非递减序列,

Educational Codeforces Round 80 (Rated for Div. 2)参加感悟

这次比赛有14000+的人报名,结果我得了266名,创了新纪录. 进过这次比赛,我有回答了1800+. 寒假到了,又可以每次比赛都打了.平时进步很慢,我希望能在寒假有更大的进步. 作为寒假第一场比赛,发挥让我还是很满意的. 开始讲题: A: http://codeforces.com/contest/1288/problem/A 这题太水了,直接是sqrt(d)-1和sqrt(d),如果它们不行,那么其他的也肯定不行. 直接上代码: 1 #include<bits/stdc++.h> 2 #d

Educational Codeforces Round 80 A-E简要题解

contest链接:https://codeforces.com/contest/1288 A. Deadline 题意:略 思路:根据题意 x + [d/(x+1)] 需要找到一个x使得上式小于等于n,即x + [d/(x+1) ] <=n,不等式两边同时+1得 x+1 + [d/(x+1)] <=n + 1当且仅当(x+1)2 = d时,式子左边最小,所有只需要判断一下最小值是否<=n+1就可以知道该不等式是否存在x满足题意了,即找到x = √d - 1,判断一下即可. AC代码:

Educational Codeforces Round 80 C. Two Arrays

http://codeforces.com/contest/1288/problem/C 题意: 用1—n构造两个长为m的数组a,b 满足a[i]<=b[i],a单调不减,b单调不增 求方案数 令dp[i][j][k] 表示构造了长度为i,a[i]=j,b[i]=k的方案数 dp[i][j][k]=Σ dp[i-1][h][p] (h<=p,h<=i,p>=k) 时间复杂度:m*n^4 前缀和.后缀和 优化: sum[i][j][k] 表示 Σ dp[i][1—j][k—n] 求的

Educational Codeforces Round 80 E. Messenger Simulator

http://codeforces.com/contest/1288/problem/E 题意: 有一个长度为n的循环队列,初始第i个位置的数字为i 有m次操作,每次操作把数字x放到队首,原队首与数字x原位置之间的数字在队列中后移一位 输出m次操作过程中,数字i在队列中最靠前和最靠后的位置 若数字i没有移动过, 它最靠前的位置就是初始位置i, 最靠后的位置就是初始位置加上移动过的大于它的数字个数 若数字i被移动过 它最靠前的位置就是1 最靠后的位置是max(初始位置加上第一次移动前移动的大于它的

Educational Codeforces Round 80. A - Deadline

题面:https://codeforces.com/contest/1288/problem/A 题目大意: Adilbek有一个特殊项目,他需要运行这个项目得到结果. 但是这个项目直接运行需要消耗d天时间. 他也可以选择优化程序以减少程序运行消耗时间. 假设他用了x天优化程序,那么最后运行程序只需要消耗天的时间(括号指向上取整). 那么总共需要消耗的天数是. 问,他能不能在n天内得到结果? 解题思路: 问能不能在n天内得到结果,只需要求出最少需要的天数与n对比即可. 可得到 那么总天数为 当且

Educational Codeforces Round 80. B - Yet Another Meme Problem

题面:https://codeforces.com/contest/1288/problem/B 题目大意: 令conc(a,b)函数得出的结果为将ab拼接得到的数字. 例如:conc(12,23)=1223 a和b不会包括前导0! 接下来,你已知A和B,问有多少对的(a,b)满足 1≤a≤A , 1≤b≤B a*b+a+b=conc(a,b) 解题思路: 想法题,只需要满足b这个数字每一位全为9,那么等式 a*b+a+b=conc(a,b) 恒成立 因为 a*b+a+b=a*(b+1)+b b

Educational Codeforces Round 80. D - Minimax Problem

题面:https://codeforces.com/contest/1288/problem/D 题目大意: 给定n个序列,每个序列元素个数严格相等于m 你需要找到两个序列a[i]和a[j],使其每个对应位置的元素取大后得到b序列  b[k]=max(a[i][k],a[j][k]) 且让b序列中的最小值最大 i可以等于j 解题思路: 二分假设这个b序列的最小值的值x 将a序列转化成01构成的二进制串存在数组b中 0表示当前位置的值<x 1表示当前位置的值>=x 每次便最多可以得到3e5个字符

Educational Codeforces Round 80 (Rated for Div. 2(A Deadline )

(A) Deadline 题目: 思路:一开始还傻傻的暴力康康....只要求出令x=n的一半就行,然后判断 1 #include<bits/stdc++.h> 2 using namespace std; 3 int main() 4 { 5 //freopen("text","r",stdin); 6 int T; 7 scanf("%d",&T); 8 while(T--) 9 { 10 //cout<<cei