这一场打得真难受
A. The Monster
解个方程就好了。
但开个visit数组暴力判断也没问题。
可以看到这份代码实际上数组可能会越界,好在没人hack,也没有FST
A
B. Not Afraid
题意记不清了,反正差不多是道模拟。
开两个bool数组记录两个集合里的人出现过没有即可。
B
C. Berzerk
博弈论 DP SG函数
按照SG函数的定义直接DP。
具体细节看代码
C
D. Legacy
图论 最短路 线段树
本质上是个最短路问题,但是一条路可能有多个起点和一个终点,或者一个起点和多个终点。
一条条建边显然T飞,不实际建边的最短路也跑不过去。
于是就用到了一个黑科技:线段树优化建边。在线段树的每个结点上向它的子结点连边,边权为0。连起点/终点是一个区间的边的时候,只要连到线段树对应的结点即可。
INF值要设得特别大。
D
E.Till I Collapse
STL 贪心 乱搞
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 using namespace std; 9 const int mxn=300010; 10 int read(){ 11 int x=0,f=1;char ch=getchar(); 12 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 13 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 14 return x*f; 15 } 16 int n; 17 int a[mxn]; 18 int pre[mxn],nxt[mxn],hd[mxn]; 19 int t[mxn]; 20 void add(int x,int v){ 21 if(!x)return; 22 while(x<=n){t[x]+=v;x+=x&-x;}return; 23 } 24 int ask(int x){ 25 int res=0; 26 for(int i=18;i>=0;i--){ 27 int p=res+(1<<i); 28 if(p<=n && t[p]<x){ 29 x-=t[p];res=p; 30 } 31 } 32 return res+1; 33 } 34 int f[mxn]; 35 vector<int>ve[mxn]; 36 int main(){ 37 int i,j; 38 n=read(); 39 for(i=1;i<=n;i++){ 40 a[i]=read(); 41 pre[i]=hd[a[i]]; 42 hd[a[i]]=i; 43 } 44 for(i=1;i<=n;i++)nxt[pre[i]]=i,ve[1].push_back(i); 45 for(i=1;i<=n;i++)if(!pre[i])add(i,1); 46 // for(i=1;i<=n;i++)printf("i:%d nxt:%d ",i,nxt[i]); 47 for(i=1;i<=n;i++){ 48 if(i>1)add(nxt[i-1],1);//记录上一个影响 49 for(j=0;j<ve[i].size();j++){ 50 int ne=ask(ve[i][j]+1); 51 ve[ne].push_back(ve[i][j]); 52 f[ve[i][j]]++; 53 } 54 add(i,-1); 55 } 56 for(i=1;i<=n;i++)printf("%d ",f[i]); 57 return 0; 58 }