CF 1110 D/E

CF 1110 D. Jongmah

题目大意:给你?\(n\)个瓷砖,每块瓷砖上有一个数字?\(a_i,(1\leq a_i\leq m)\)。你可以将三个有连续数字?\((比如3,4,5)\)的瓷砖或者三个数字相同?\((比如7,7,7)\)的瓷砖组成一个三元组。每个瓷砖只能用一次。问最多可以得到多少个三元组。?

比赛的时候好像全场A穿,然而并没有想到 (TAT

一开始想到\(DP\),但是?觉得状态数太大;于是想了奇奇怪怪的贪心,但是都能找到反例。

这道题的关键是要发现一个性质:同一位置上连续三个瓷砖匹配不会超过\(2\)个。因为如果凑够了\(3\)个就可以分别单独匹配了。这样一来状态数就少了:设\(f[i][j][k]\)表示\(DP\)到编号为\(i\)的瓷砖,以\(i-1\)结尾的连续匹配进行了\(j\)次,以\(i\)结尾的连续匹配进行了\(k\)次的最大三元组数。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
#include<queue>
#include<vector>
#include<map>
#define ll long long
#define N 1000005

using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}

int n,m;
int f[N][3][3],sum[N];
int main() {
    n=Get(),m=Get();
    int a;
    for(int i=1;i<=n;i++) {
        a=Get();
        sum[a]++;
    }
    memset(f,-0x3f,sizeof(f));
    f[2][0][0]=0;
    for(int i=2;i<m;i++) {
        for(int j=0;j<3;j++) {
            for(int k=0;k<3;k++) {
                if(f[i][j][k]<0) continue ;
                for(int q=0;q<3;q++) {
                    if(sum[i+1]<q) break;
                    if(sum[i]<k+q) break;
                    if(sum[i-1]<j+k+q) break;
                    f[i+1][k][q]=max(f[i+1][k][q],f[i][j][k]+(sum[i-1]-j-k-q)/3+q);
                }
            }
        }
    }
    int ans=0;
    for(int i=0;i<3;i++)
        for(int j=0;j<3;j++)
            ans=max(ans,f[m][i][j]+(sum[m]-j)/3+(sum[m-1]-i-j)/3);
    cout<<ans;
    return 0;
}

总结:发现这种非一般套路的\(DP\)或者贪心题时要去发现题目的特殊性质,往往特殊性质是解题的关键。



CF 1110 E. Magic Stones

题目大意:给你两个长度为\(n\)的序列\(c\)和\(t\)。你可以对\(c\)进行任意次操作,每次操作选取位置\(i(2\leq i\leq n-1)\),然后将\(c_i\)变成\(c_{i-1}+c_{i+1}-c_i\)。

这题太神了,不过好像比赛时也被A穿了。

我们设\(d_i=c_{i+1}-c_i(1\leq i \leq n-1)\)。我们会发现,对\(c_i\)进行上述操作后,交换了\(d_{i-1}\)与\(d_i\)。

所以我们将两个数列的\(d\)数组求出来,排序后直接比较就行了。还有要判断\(c_1==t_1\)。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
#include<queue>
#include<vector>
#include<map>
#define ll long long
#define N 200005

using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}

int n;
int c[N],t[N];
int dc[N],dt[N];
int main() {
    n=Get();
    for(int i=1;i<=n;i++) c[i]=Get();
    for(int i=1;i<=n;i++) t[i]=Get();
    for(int i=1;i<n;i++) dc[i]=c[i+1]-c[i];
    for(int i=1;i<n;i++) dt[i]=t[i+1]-t[i];
    if(c[1]!=t[1]) {cout<<"No";return 0;}
    sort(dc+1,dc+n);
    sort(dt+1,dt+n);
    for(int i=0;i<=n;i++) {
        if(dc[i]!=dt[i]) {cout<<"No";return 0;}
    }
    cout<<"Yes";
    return 0;
}

原文地址:https://www.cnblogs.com/hchhch233/p/10356186.html

时间: 2024-11-13 02:13:59

CF 1110 D/E的相关文章

CF - 1110 C Meaningless Operations

题目传送门 题解: 首先根据观察,很容易发的是: x != (1<<k) - 1 时候 答案就是, 将x二进制下再最高位后的0都变成1. 然后就是考虑 x == (1<<k) - 1的时候 同样根据观察可以得到  b ^ x =  x - b, b&x = b 所以就是将x拆成2个数, 然后这2个数的gcd最大. 我们就最后找x的因子. 如 x = b * c 那么们就可以把2个数分成 c , (b-1) * c,gcd 为 c. 或者 b , b * (c-1)   gc

CF 1110 D. Jongmah

D. Jongmah 链接 题意: 一些数字,有两种方式组成一个三元组,[x,x,x],[x,x+1,x+2],每个数字只能用一次,求最多组成多少三元组. 分析: 因为每三个[x,x+1,x+2]是可以拆成[x,x,x],[x+1,x+1,x+1],[x+2,x+2,x+2]的,所以可以认为对于以x开始的[x,x+1,x+2]最多有两个. 于是可以dp[i][x][y]表示到第i个数字,存在x个[i-1,i,i+1],y个[i,i+1,i+2],最多组成多少个三元组(这些三元组的右端点在i以内,

CF 1110 E. Magic Stones

E. Magic Stones 链接 题意: 给定两个数组,每次可以对一个数组选一个位置i($2 \leq i \leq n - 1$),让a[i]=a[i-1]+a[i+1]-a[i],或者b[i]=b[i-1]+b[i+1]-b[i].问进行一些操作后,a和b能否相同. 分析: 考虑一次操作会变成什么样子. a b c a a+c-b c 我们发现这些数字差分后是不变的.于是对两个数组差分后,排序,看是否一样即可.注意判一下1和n是否相等. 代码: #include<cstdio> #in

CF 1320D Reachable Strings 后缀数组

确定性解法:后缀数组 众所周知 hash 由于不能完全避免冲突常常会被 cf hacker 卡掉,此题有更稳定的解法 考虑将原串进行简化,由于只有连续的 1 会造成不确定的匹配,可以只对 0 建立一个新串 对于一段连续的 1,后面的 0 建立新字符,如果有奇数个 1 就建立 1,偶数个就建立 0 例如: 1110 -> 1,110 -> 0,11011 -> 0 由于最后的 1 是没有后导 0 的就不计入新串 然后新串的 lcp 就可以对应到原串的对应位置,新串 lcp 匹配就等价于原串

微信 {&quot;errcode&quot;:40029,&quot;errmsg&quot;:&quot;invalid code, hints: [ req_id: Cf.y.a0389s108 ]&quot;}

{"errcode":40029,"errmsg":"invalid code, hints: [ req_id: Cf.y.a0389s108 ]"} 问题:微信网页授权后,获取到 openid 了,一刷新又没了 微信网页授权获取到的 code 只能使用一次(5分钟内有效),使用一次后,马上失效. 页面授权跳转成功,根据 code 也换取到 openid 了. 此时刷新页面,并不会再次进行授权,而是直接刷新了一下上一次授权跳转后的链接,带的还是

1110 最近共同祖先

题目来源:https://acm.zzuli.edu.cn/zzuliacm/problem.php?id=1110Description 如上图所示,由正整数1, 2, 3, ...组成了一棵无限大的二叉树.从某一个结点到根结 点(编号是1 的结点)都有一条唯一的路径,比如从10 到根结点的路径是(10, 5, 2, 1), 从4 到根结点的路径是(4, 2, 1),从该结点到根结点的路径上的所有结点称为该结点的祖先.现在的问题就是,给定x 和y,求x和y的最近共同祖先,比如,10和4最近共同

CF with friends and user&#39;s influence considered on NYC data(updated Aug,11st)

Here is the code link: https://github.com/FassyGit/LightFM_liu/blob/master/U_F1.py I use NYC data as other experimens. The split of the training data was seperated by the timeline, and I have normalised the interaction matrix by replacing the checkin

CF 750

今天CF打的块残废了     就是一废物 A 在24点之前到 直接模拟即可 #include<stdio.h> #include<algorithm> #include<cstring> #include<string> #include<cmath> using namespace std; #define LL long long #define MAXN 1010 #define inf 1000000000.0 int main() {

CF #394 (2) 5/6

Codeforces Round #394 (Div. 2) 总结:有毒的一场比赛.做了三题,结果A被叉,B.C挂综测,还hack失败一发,第一次在CF体会到了-50分的感觉..不知道是不是人品好,比赛时room炸了,然后,unrated.. A  水题,判一下0 0,然后abs(a-b)<=1 B  水题,组个间距比较一下,但一个数的时候要判一下 C  直接暴力上的题 D  也是xjb暴力 题意:给出n,l,r, a[], p[],另有两个数组b[], c[],ci=bi-ai.l<=ai,