Preface
现在先把之前打掉的题目先写了,不然时间一长又忘记了
这场不知道为什么打的极其抽象,A都能写WA而且C一个细节写挂调了好久,最后30min才做出D,罚时起飞
连着两场掉分了,感觉有点难受
A. Working Week
刚开始SB了想错了一个地方WA了一发
其实就是令\(l_1=1\)(即Day2设为off),然后把剩下的数尽量分成三份即可
最后答案就是\(\lfloor\frac{n}{3}\rfloor-2\)
#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
int t,n;
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
for (scanf("%d",&t);t;--t)
scanf("%d",&n),printf("%d\n",n/3-2);
return 0;
}
B. Tea with Tangerines
SB题,不难发现每次分割出来的最大块是\(2a_1-1\),直接做即可
#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
int t,n,x,y; long long ans;
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
for (scanf("%d",&t);t;--t)
{
scanf("%d%d",&n,&x); x=x*2-1; ans=0;
for (RI i=1;i<n;++i)
scanf("%d",&y),ans+=(y-1)/x; printf("%lld\n",ans);
}
return 0;
}
C. Phase Shift
刚开始没考虑太多就直接开写了,结果边写边改思路导致写的很慢,下次一定要理清思路再开写
首先我们考虑维护一下所有数的变换关系,肯定是若干条链
然后考虑当出现一个它的前驱未出现的字符时,可以选择让这个字符的前驱指向所有链的末尾元素中最小的那个,或者是剩下的未出现字符中字典序最小的那个
然后当所有字符都出现过之后把最后的一条链首尾相接即可
#include<cstdio>
#include<vector>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
const int N=100005;
int t,n,frm[26],nxt[26]; char s[N]; bool vis[26]; vector <int> bot;
inline int getmin(CI avoid)
{
RI i; int mn=26; for (i=0;i<bot.size();++i) if (bot[i]!=avoid) mn=min(mn,bot[i]); return mn;
}
inline void modify(CI x,CI y)
{
RI i; for (auto it=bot.begin();it!=bot.end();) if (*it==y) it=bot.erase(it); else ++it;
for (i=0;i<bot.size();++i) if (bot[i]==x) bot[i]=y;
}
inline int getbot(int x)
{
while (~nxt[x]) x=nxt[x]; return x;
}
inline int get(CI ch)
{
if (~frm[ch]) return frm[ch]; RI i;
bool flag=1; for (i=0;i<26&&flag;++i) if (i!=ch&&!~frm[i]) flag=0;
if (flag) return bot[0];
for (i=0;i<26;++i) if (!vis[i]) break;
int tmp; if (bot.size()>0&&getmin(getbot(ch))<i)
return tmp=getmin(getbot(ch)),modify(tmp,getbot(ch)),tmp;
return bot.push_back(getbot(ch)),i;
}
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
for (scanf("%d",&t);t;--t)
{
RI i,j; for (scanf("%d%s",&n,s+1),i=0;i<26;++i) vis[i]=0,frm[i]=nxt[i]=-1;
for (bot.clear(),i=1;i<=n;++i)
{
int nw=s[i]-'a'; vis[nw]=1; int fr=get(nw);
vis[frm[nw]=fr]=1; nxt[fr]=nw; putchar(frm[nw]+'a');
if (!bot.size()) bot.push_back(nw);
}
putchar('\n');
}
return 0;
}
D. Meta-set
刚开始没发现一个重要性质觉得好难,后来转念一想Div2的D不都是SB题嘛就迎刃而解(PS:前两场的D都没做出来)
考虑数据范围和时限显然是允许我们暴力枚举所有的set
的,我们发现可以设一个数组\(c\)来表示每张牌出现在几个set
里
最后的答案就是\(\sum_{i=1}^n C_{c_i}^2\),原因是因为Meta-set
中有且仅有一张牌为两个set
的公共部分
换句话说,即不存在\((x,y,p)\)和\((x,y,q),x\ne y\ne p\ne q\)均为set
的情况
证明也很简单,因为若\((x,y,z)\)为set
,那么\(x,y\)的每一个feature
都会使\(z\)在这一维上的取法固定,因此不会存在上面的情况
注意一个细节再判断每一维是否合法时可以直接用三个对应位置的和是否是\(3\)的倍数来验证,不然如果实现不好的可能会T(比赛的时候就是这样)
复杂度\(O(n^3k)\),由于跑不满+CF神机+超大时限可以通过此题
#include<cstdio>
#include<algorithm>
#define RI register int
#define CI const int&
using namespace std;
const int N=1005;
int n,s,a[N][25],num[N],d[3]; long long ans;
inline bool check(CI x,CI y,CI z)
{
for (RI i=1;i<=s;++i) if ((a[x][i]+a[y][i]+a[z][i])%3) return 0; return 1;
}
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
RI i,j,k; for (scanf("%d%d",&n,&s),i=1;i<=n;++i)
for (j=1;j<=s;++j) scanf("%d",&a[i][j]);
for (i=1;i<=n;++i) for (j=i+1;j<=n;++j) for (k=j+1;k<=n;++k)
if (check(i,j,k)) ++num[i],++num[j],++num[k];
for (i=1;i<=n;++i) ans+=1LL*num[i]*(num[i]-1)/2LL;
return printf("%lld",ans),0;
}
标签:CI,set,int,Codeforces,824,Div,include,RI,define
From: https://www.cnblogs.com/cjjsb/p/16756813.html