首页 > 其他分享 >2020-2021 ICPC Southeastern European Regional Programming Contest (SEERC 2020)

2020-2021 ICPC Southeastern European Regional Programming Contest (SEERC 2020)

时间:2024-01-19 20:34:54浏览次数:38  
标签:const SEERC Contest int ret 2020 include RI define

Preface

最害怕的一集,徐神感冒身体不适只能口胡前半场,祁神中途也有事下机导致一段时间内只有我一个人在写题

最后也是不负众望体现出没有队友我究竟是多么地彩笔,后面也索性开摆了直接后面3h梭哈写H题(主要写个假做法浪费很长时间)最后喜被卡常

打完这场特意叫了一天休息,一是为了徐神恢复身体,二是为了补一补这场剩下没写的可做题


A. Archeologists

思博题,比赛的时候感觉很像个模拟费用流但就是流不来,后面一看果然是这玩意

首先考虑一个转化,对\(\{1,2,\cdots,n\}\)上的位置做线段覆盖,要求端点必须是整点,且每个点作为左右端点至多一次

设\(i\)点被覆盖的次数为\(c_i\),则最后的答案为\(\sum c_i\times p_i\)

对原数组求出前缀和\(s_i\)后转化为在\(\{0,1,2,\cdots,n\}\)上选择\(n+1\)个区间,左端点对应的位置为减,右端点对应的位置为加,求最大权值

考虑用一个费用流模型来刻画,首先\(i\to i+1\)连容量\(\infty\),费用为\(0\)的边,然后\(S\to i\)连容量\(1\),费用为\(-s_i\)的边;\(i\to T\)连容量\(1\),费用为\(s_i\)的边,其最大费用最大流就是答案

考虑模拟费用流,我们直接倒着维护,若当前点选择作为左端点,则其将匹配后缀中权值最大的出边;否则将其作为右端点加入待选中

注意到还需实现反悔过程,这题中因为\(a\to b,b\to c\)等价于\(a\to c\),因此选该点做左端点时也要将\(s_i\)加入待选中以实现反悔(退流)操作

用大根堆维护待选的出边,总复杂度\(O(n\log n)\)

#include<cstdio>
#include<iostream>
#include<queue>
#define int long long
#define RI register int
#define CI const int&
using namespace std;
const int N=250005;
int n,p[N],pfx[N],ans; priority_queue <int> hp;
signed main()
{
	RI i; for (scanf("%lld",&n),i=1;i<=n;++i)
	scanf("%lld",&p[i]),pfx[i]=pfx[i-1]+p[i];
	for (hp.push(pfx[n]),i=n-1;i>=0;--i)
	{
		if (hp.top()-pfx[i]>0) ans+=hp.top()-pfx[i],hp.pop(),hp.push(pfx[i]);
		hp.push(pfx[i]);
	}
	return printf("%lld",ans),0;
}

B. Reverse Game

差点被签到题腐乳,还好祁神发现了操作的本质

考虑翻转10会让原序列的逆序对减少\(1\),而其它三种操作均会让逆序对减少\(2\)

同时不难发现如果可以进行后面三种操作,也一定能进行第一种操作

因此问题转化为有一堆石子,两人轮流取,每次取\(1,2\)颗,问谁必胜

这是个经典的Bash博弈模型,按照初始状态的逆序对数量对\(3\)的余数判断即可

#include<bits/stdc++.h>
using namespace std;
#define int long long

string str;
signed main(){
	ios::sync_with_stdio(0); cin.tie(0);
	cin >> str;
	int n = str.length();
	int cnt0=0;
	int res=0;
	for (int i=n-1; i>=0; --i){
		if (str[i]=='1') res+=cnt0;
		else ++cnt0;
	}
	if (res%3==0) cout << "Bob\n";
	else cout << "Alice\n";
	return 0;	
}

C. 3-colorings

哈人,还有题答,鉴定为做不了一点


D. Disk Sort

比赛时候没仔细想,提出了正确的做法但感觉不对(其实是懒得写),赛后写了下发现也不难写

考虑进行\(n-1\)轮,每次将一种颜色复原并保证该轮后仍存在一根空的柱子(\(n-1\)轮后最后一种颜色会自动复原)

那么只要保证每一轮至多进行\(6\)次操作,最后的操作总数就是\(6(n-1)+3=6n-3<6n\),符合题意

考虑我们把层数从上到下标为\(0,1,2\),那么考虑对某种颜色,其高度分布记为\((a,b,c)\),不妨设\(a\le b\le c\)

直觉告诉我们先恢复更靠近上层的颜色盘总是最优的,同时根据抽屉原理,总存在某个颜色的盘满足\(a+b+c\le 3\)

然后手玩一下所有情况会发现绝大多数都可以在\(6\)轮之内完成,但只有\((1,1,1)\)的情况除外

但再仔细分析一波会发现总存在一种颜色,使得其存在一个处于第\(0\)层的盘面,并且另外两个盘面不同时位于第\(2\)层,对于这种情况我们总能做到\(6\)步之内的操作

实现的话可以从上往下依次归位,但要注意操作的盘在同一柱子上的一些细节,具体看代码

#include<cstdio>
#include<iostream>
#include<deque>
#include<vector>
#include<algorithm>
#define RI register int
#define CI const int&
#define fi first
#define se second
using namespace std;
typedef pair <int,int> pi;
const int N=1005;
int n,x; deque <int> s[N]; vector <pi> pos[N]; vector <pi> ans;
inline void move(CI x,CI y)
{
	ans.push_back(pi(x,y));
	int v=s[x].front(); pi it=pi(3-s[x].size(),x); s[x].pop_front();
	for (RI i=0;i<pos[v].size();++i) if (pos[v][i]==it)
	{
		pos[v].erase(pos[v].begin()+i); break;
	}
	pos[v].push_back(pi(2-s[y].size(),y)); s[y].push_front(v);
}
int main()
{
	RI i,j; for (scanf("%d",&n),i=0;i<3;++i)
	for (j=1;j<=n;++j) scanf("%d",&x),s[j].push_back(x),pos[x].push_back(pi(i,j));
	for (;;)
	{
		int tar=-1,col=-1;
		for (i=1;i<=n+1;++i) if (s[i].empty()) { tar=i; break; }
		for (i=1;i<=n;++i)
		{
			if (pos[i][0].se==pos[i][1].se&&pos[i][0].se==pos[i][2].se) continue;
			sort(pos[i].begin(),pos[i].end());
			if (pos[i][0].fi==1||pos[i][0].fi+pos[i][1].fi+pos[i][2].fi>3) continue;
			col=i; break;
		}
		if (col==-1) break; vector <int> spare;
		vector <pi> tmp=pos[col];
		for (i=0;i<3;++i)
		{
			int idx=tmp[i].se;
			while (s[idx].front()!=col)
			{
				for (j=0;j<spare.size();++j)
				if (idx!=spare[j])
				{
					move(idx,spare[j]); spare.erase(spare.begin()+j);
					spare.push_back(idx); break;
				}
			}
			move(idx,tar); spare.push_back(idx);
		}
		int mn=4,num=-1; for (i=1;i<=n+1;++i) if (s[i].size()<mn) mn=s[i].size(),num=i;
		while (!s[num].empty())
		{
			int unfull=-1; for (i=1;i<=n+1;++i)
			if (i!=num&&s[i].size()<3) { unfull=i; break; }
			move(num,unfull);
		}
	}
	if (!s[n+1].empty())
	{
		int tar=-1; for (i=1;i<=n;++i) if (s[i].empty()) { tar=i; break; }
		while (!s[n+1].empty()) move(n+1,tar);
	}
	printf("%d\n",ans.size());
	for (auto [x,y]:ans) printf("%d %d\n",x,y);
	return 0;
}

E. Divisible by 3

大力出奇迹,手玩所有Case找到规律直接艹过

先将所有数\(\bmod 3\),考虑对于一个区间,其中\(0\)的个数显然没有影响,不妨设其中\(1,2\)的个数各有\(x,y\)个

推个贡献的式子然后大力分讨一下最后贡献是\(3\)的倍数的情况,发现当且仅当\((x\bmod 3,y\bmod 3)=(0,0),(0,1),(1,0)\)时成立,拿个前缀和维护一下即可

#include<cstdio>
#include<iostream>
#include<cstring>
#define int long long
#define RI register int
#define CI const int&
using namespace std;
const int N=500005,d1[3]={0,0,1},d2[3]={0,1,0};
int n,a[N],bkt[3][3],cur1,cur2,ans;
signed main()
{
	RI i,j; for (scanf("%lld",&n),i=1;i<=n;++i) scanf("%lld",&a[i]),a[i]%=3;
	for (++bkt[cur1=0][cur2=0],i=1;i<=n;++i)
	{
		cur1+=(a[i]==1); cur2+=(a[i]==2); cur1%=3; cur2%=3;
		for (j=0;j<3;++j)
		{
			int pre1=(cur1-d1[j]+3)%3,pre2=(cur2-d2[j]+3)%3;
			ans+=bkt[pre1][pre2];
		}
		++bkt[cur1][cur2];
	}	
	return printf("%lld",ans),0;
}

F. Fence Job

首先考虑转化题意,对于每个位置\(i\)求出\(h_i\)为最小值的极长区间,记为\([l_i,r_i]\),则可以看作每个数可以对\([l_i,r_i]\)任意赋值

然后直接大力DP,设\(f_{i,j}\)表示考虑了前\(i\)个位置,最后的序列确定了\(j\)个元素的方案数

若选择第\(i\)个位置不确定最终序列,则\(f_{i,j}\leftarrow f_{i-1,j}\),否则有:

\[f_{i,j}\leftarrow\sum_{k=l_i-1}^j f_{i-1,k}\ \ \ (j\in[l_i,r_i]) \]

拿个前缀和优化一下即可做到\(O(n^2)\)

#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
const int N=3005,mod=1e9+7;
int n,a[N],l[N],r[N],f[N][N],g[N][N];
int main()
{
	RI i,j; for (scanf("%d",&n),i=1;i<=n;++i) scanf("%d",&a[i]);
	for (i=1;i<=n;++i)
	{
		for (l[i]=1,j=i-1;j>=1;--j) if (a[j]<a[i]) { l[i]=j+1; break; }
		for (r[i]=n,j=i+1;j<=n;++j) if (a[j]<a[i]) { r[i]=j-1; break; }
	}
	//for (i=1;i<=n;++i) printf("(%d,%d)\n",l[i],r[i]);
	for (f[0][0]=g[0][0]=1,i=1;i<=n;++i) g[0][i]=1;
	for (i=1;i<=n;++i)
	{
		for (j=0;j<=n;++j) f[i][j]=f[i-1][j];
		for (j=l[i];j<=r[i];++j) if (l[i]-1<=j)
		f[i][j]=(g[i-1][j]-(l[i]-2>=0?g[i-1][l[i]-2]:0)+mod)%mod;
		for (g[i][0]=f[i][0],j=1;j<=n;++j) g[i][j]=(g[i][j-1]+f[i][j])%mod;
	}
	return printf("%d",f[n][n]),0;
}

G. Simple Hull

题目没看,弃疗


H. AND = OR

最害怕的一题,写+对拍了2h才发现做法假了,直接心态爆炸

因为AND操作总会让数变小,OR操作总会让数变大,因此可以将所有数升序排序后,枚举分界点,前半部分或起来,后半部分与起来

然后刚开始以为这个是可二分的,写了个二分答案+归并树查询的做法,不仅三个\(\log\)复杂度爆炸,还WA到天上去了

后面又冷静思考了一波发现,上面的操作并没有太多利用位运算的特性,其实两个操作的性质对于另一个刻画指标也是成立的,就是某个数二进制下\(1\)的个数

具体地,我们枚举分界点\(k\),钦定二进制下\(1\)的个数\(<k\)的都用或操作,\(>k\)的都用与操作,若\(=k\)的数有多个则一定无解,否则\(=k\)的数可以任意选择加入哪个集合中

直接开\(30\)棵线段树,每棵线段树维护区间ANDOR,以及区间内所有数是否相同(相同的话维护个数)即可

总复杂度\(O(n\log n\log a_i)\),但由于我写的时候为了维护边界情况用了常数极大的写法,最后成功被卡常

(以下代码交上去会TLE,但和能通过的代码对拍过正确性没有问题)

#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
const int N=100005,INF=(1<<30)-1;
struct ifo
{
	int same,val,cnt;
	inline ifo(CI S=1,CI V=-1,CI C=0)
	{
		same=S; val=V; cnt=C;
	}
	friend inline ifo operator + (const ifo& A,const ifo& B)
	{
		if (A.val==-1) return B; if (B.val==-1) return A;
		if (A.same==0||B.same==0) return ifo(0,0,0);
		if (A.val!=B.val) return ifo(0,0,0);
		return ifo(1,A.val,A.cnt+B.cnt);
	}
};
struct num
{
	int val,ext;
	inline num(CI V=-1,CI E=0)
	{
		val=V; ext=E;
	}
	friend inline num operator | (const num& A,const num& B)
	{
		return num(A.val|B.val,A.ext|B.ext);
	}
	friend inline num operator & (const num& A,const num& B)
	{
		return num(A.val&B.val,A.ext|B.ext);
	}
};
int n,q,a[N],l,r;
class Segment_Tree
{
	private:
		ifo O[N<<2]; num OR[N<<2],AND[N<<2];
	public:
		#define TN CI now=1,CI l=1,CI r=n
		#define LS now<<1,l,mid
		#define RS now<<1|1,mid+1,r
		inline void init(void)
		{
			for (RI i=1;i<=(n<<2);++i) OR[i]=num(0,0),AND[i]=num(INF,0),O[i]=ifo();
		}
		inline void updata(CI pos,CI mv,TN)
		{
			if (l==r)
			{
				OR[now]=AND[now]=num(mv,1);	O[now]=ifo(1,mv,1); return;
			}
			int mid=l+r>>1; if (pos<=mid) updata(pos,mv,LS); else updata(pos,mv,RS);
			OR[now]=OR[now<<1]|OR[now<<1|1];
			AND[now]=AND[now<<1]&AND[now<<1|1];
			O[now]=O[now<<1]+O[now<<1|1];
		}
		inline num query_or(CI beg,CI end,TN)
		{
			if (beg<=l&&r<=end) return OR[now]; int mid=l+r>>1; num ret=num(0,0);
			if (beg<=mid) ret=ret|query_or(beg,end,LS); if (end>mid) ret=ret|query_or(beg,end,RS); return ret;
		}
		inline num query_and(CI beg,CI end,TN)
		{
			if (beg<=l&&r<=end) return AND[now]; int mid=l+r>>1; num ret=num(INF,0);
			if (beg<=mid) ret=ret&query_and(beg,end,LS); if (end>mid) ret=ret&query_and(beg,end,RS); return ret;
		}
		inline ifo query_ifo(CI beg,CI end,TN)
		{
			if (beg<=l&&r<=end) return O[now]; int mid=l+r>>1; ifo ret=ifo();
			if (beg<=mid) ret=ret+query_ifo(beg,end,LS); if (end>mid) ret=ret+query_ifo(beg,end,RS); return ret;
		}
		#undef TN
		#undef LS
		#undef RS
}SEG[31];
int main()
{
	//freopen("H.in","r",stdin); freopen("H.out","w",stdout);
	RI i; for (scanf("%d%d",&n,&q),i=1;i<=n;++i) scanf("%d",&a[i]);
	for (i=0;i<=30;++i) SEG[i].init();
	for (i=1;i<=n;++i) SEG[__builtin_popcount(a[i])].updata(i,a[i]);
	for (;q;--q)
	{
		scanf("%d%d",&l,&r); static num pre[31],suf[31];
		for (i=0;i<=30;++i) pre[i]=SEG[i].query_or(l,r),suf[i]=SEG[i].query_and(l,r);
		for (i=1;i<=30;++i) pre[i]=pre[i]|pre[i-1];
		for (i=29;i>=0;--i) suf[i]=suf[i]&suf[i+1];
		int flag=0; for (i=0;i<=30&&!flag;++i)
		{
			ifo it=SEG[i].query_ifo(l,r); if (it.same==0) continue;
			num OR=(i>0?pre[i-1]:num(0,0)),AND=(i<30?suf[i+1]:num(INF,0));
			for (RI u=0;u<=min(it.cnt,2);++u)
			{
				int v=min(it.cnt-u,2); int Or=OR.val,And=AND.val;
				if (OR.ext==0&&u==0) continue;
				if (AND.ext==0&&v==0) continue;
				if (u) Or|=it.val; if (v) And&=it.val;
				if (Or==And) { flag=1; break; }
			}
		}
		puts(flag?"YES":"NO");
	}
	return 0;
}

I. Modulo Permutations

经典看到数数题就扔给队友,然后昨天只有祁神一个人想这个题然后也犯病了

首先由于\(1,2\)怎么放都合法,因此放在最后考虑,先把\(3\sim n\)的数确定下来

考虑从大到小放数,\(f_{i,j}\)代表当前分出来的两个部分的各自最小的数

如果当前放的是\(x\),可以直接从\(f_{x+1,j}\)转移到\(f_{x,j}\);否则如果\(j\bmod x\le 2\),可以从\(f_{x+1,j}\)转移到\(f_{x,x+1}\)

手玩一下发现可以压掉一维,同时满足上述转移的第二种情况的数是有倍数关系的,直接做复杂度就是调和级数的

总复杂度\(O(n\log n)\)

#include<bits/stdc++.h>
using namespace std;
#define int long long

const int MOD = 1e9+7;
void add(int &x, int a){if ((x+=a)>=MOD) x-=MOD;}

const int N = 1e6+5;
int f[N];

signed main(){
	int n; cin >> n;
	if (1==n) cout << "1\n";
	else if (2==n) cout << "2\n";
	else{
		for (int x=n-1; x>=3; --x){
			f[x+1]=1;
			for (int i=1; i*x<=n; ++i){
				for (int j=0; j<=2; ++j){
					if (i*x+j<=x+1 || i*x+j>n) continue;
					add(f[x+1], f[i*x+j]);
				}
			}
		}
		int ans=1;
		for (int i=4; i<=n; ++i) add(ans, f[i]);
	//	printf("ans=%lld\n", ans);
		cout << ans*2%MOD*n%MOD << '\n';
	}
	return 0;	
}


J. One Piece

感觉是个可做题,但还没太搞懂先弃了


K. Codenames

放AK题,鉴定为寄


L. Neo-Robin Hood

这题其实基本还是徐神教的,不敢想象如果真的没有徐神要被打成啥样

首先根据上次VP的那场的某个题的思路,考虑对于偷\(i\)买\(j\)这个操作,它相比于偷\(j\)买\(i\)这个操作更优时一定满足\(m_i-p_j>m_j-p_i\),即\(m_i+p_i>m_j+p_j\)

因此我们按照\(m_i+p_i\)从大到小排序后,不难发现偷的一定是一段前缀,而买的一定是一段与之不相交的后缀

如果直接枚举分界点,还是不太好处理问题,但如果加上两边各要选多少个数后就很简单了

因此想到二分答案,枚举分界点后用堆快速维护两边选若干个数的代价,总复杂度\(O(n\log^2 n)\)

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#define int long long
#define RI register int
#define CI const int&
using namespace std;
const int N=100005;
struct ifo
{
	int m,p;
	friend inline bool operator < (const ifo& A,const ifo& B)
	{
		return A.m+A.p>B.m+B.p;
	}
}a[N]; int n;
inline bool check(CI k)
{
	RI i; static int pre[N],suf[N];
	priority_queue <int,vector <int>,greater <int>> sml;
	for (pre[0]=0,i=1;i<=k;++i) pre[i]=pre[i-1]+a[i].m,sml.push(a[i].m);
	for (i=k+1;i<=n;++i) sml.push(a[i].m),pre[i]=pre[i-1]+a[i].m-sml.top(),sml.pop();
	priority_queue <int> big;
	for (suf[n+1]=0,i=1;i<=k;++i) suf[n-i+1]=suf[n-i+2]+a[n-i+1].p,big.push(a[n-i+1].p);
	for (i=k+1;i<=n;++i) big.push(a[n-i+1].p),suf[n-i+1]=suf[n-i+2]+a[n-i+1].p-big.top(),big.pop();
	for (i=k;n-i>=k;++i) if (pre[i]>=suf[i+1]) return 1;
	return 0;
}
signed main()
{
	RI i; for (scanf("%lld",&n),i=1;i<=n;++i) scanf("%lld",&a[i].m);
	for (i=1;i<=n;++i) scanf("%lld",&a[i].p); sort(a+1,a+n+1);
	int l=1,r=n/2,mid,ret=0; while (l<=r)
	if (check(mid=l+r>>1)) ret=mid,l=mid+1; else r=mid-1;
	return printf("%lld",ret),0;
}

M. Mistake

不难发现将每个数第一次出现归为一组,第二次出现归为一组,以此类推,如果这样都无解那么其它方案一定也无解

因此这题输入的图限制其实是假的,就是个纯纯的诈骗题

#include<bits/stdc++.h>
using namespace std;

const int N = 5e5+5;
int n, k, m;
int cnt[N], ans[N];
signed main(){
	ios::sync_with_stdio(0); cin.tie(0);
	cin >> n >> k >> m;
	for (int i=1; i<=m; ++i){
		int a, b; cin >> a >> b;
	}
	for (int i=1; i<=n*k; ++i){
		int a; cin >> a;
		++cnt[a];
		ans[i] = cnt[a];
	}
	for (int i=1; i<=n*k; ++i) cout << ans[i] << ' ';
	cout << '\n';
	return 0;	
}

Postscript

徐神是我们的红太阳,没有他我们都不能活

标签:const,SEERC,Contest,int,ret,2020,include,RI,define
From: https://www.cnblogs.com/cjjsb/p/17975530

相关文章

  • Contest3376 - 2024寒假集训-排位赛竞赛(一)
    A:幂位和高精度。用高精度加法或乘法算出\(2^{1000}\),再将各位累加即为答案。#include<bits/stdc++.h>usingnamespacestd;#definecctieios::sync_with_stdio(0);cin.tie(0);cout.tie(0)stringAP_add(stringA,stringB)//高精度加法{intlena=A.size()......
  • AtCoder Beginner Contest 335
    A-2023(abc335A)题目大意给定一个字符串,将最后一位改成4。解题思路模拟即可。神奇的代码#include<bits/stdc++.h>usingnamespacestd;usingLL=longlong;intmain(void){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);strings;......
  • The 2021 Sichuan Provincial Collegiate Programming Contest
    题目链接:The2021SichuanProvincialCollegiateProgrammingContestA.Chuanpai题意:定义每一张川牌包含两个数字x,y,并且1<=x<= y<=6,求牌面上数字之和为n的牌种类解题思路:签到,预处理枚举即可查看代码map<int,int>mp;voidinit(){ for(inti=1;i<=6;i......
  • AT_hitachi2020_f Preserve Diameter
    哦哦牛皮给定一棵树,你需要加入一些边,使得它成为一个简单无向图,要求:图的直径等于原树直径加入任何一条新边都会让图的直径变小。求方案数对\(998244353\)取模。\(1\len\le2\times10^5\)考虑找到新图的一对距离最远的点,将其它点按照到它们的距离标号并分层。由于第......
  • 2021 ICPC Southeastern Europe Regional Contest
    Preface这场打的挺好,感觉在题目难度不小的情况下能写出10题还是挺猛的可惜最后时间差一点不然甚至能再写出来一个EA.KingofStringComparison签到,本来徐神跟我说写个二分+Hash,然后我库库上去一顿写刚抄完板子就被赶下来了直接从后往前扫,记录距离当前最近的不同的位置出现......
  • AtCoder Beginner Contest 336
    题目链接:AtCoderBeginnerContest336A-LongLoong题意:输出Long,其中'o'的数量等于n解题思路:签到(其实没看清楚题目wa了一发)查看代码voidsolve(){ intn; cin>>n; cout<<'L'; while(n--)cout<<'o'; cout<<"ng";}......
  • 2020-2021 ACM-ICPC Latin American Regional Programming Contest J. Job Allocator
    Preface今天因为下午被强行拉回老家了,而且没带电脑回去然后就变成了徐神和祁神两个人写,我拿个手机在后面口胡了3h最后变成了在缺我一个人的前提下还能4h过10题的情况,感觉就算我在的话最多就是快点过H然后把剩下的时间拿去写个J这场因为没啥参与就不写整场的博客了,把赛后写的这......
  • AtCoder Grand Contest 046 F Forbidden Tournament
    洛谷传送门AtCoder传送门太厉害了!!!!!!首先竞赛图有个性质,若存在环则一定存在三元环。先把DAG的情况(一条链)特判了。然后缩点。发现非链底的部分不能存在大小\(>1\)的SCC。所以枚举非链底的部分有多少点,转化为SCC的情况。发现对于任意点(设为\(1\)号点),它的前驱连成一条链......
  • 美国科技 5 巨头,研发狂烧 2020 亿刀!亚马逊 732 亿全球第一丨 RTE 开发者日报 Vol.127
       开发者朋友们大家好: 这里是「RTE开发者日报」,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享RTE(RealTimeEngagement)领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「有看点的会议」,......
  • 【pwn】wustctf2020_closed --exec重定向
    这道题先来看一下ida这道题的代码逻辑很简单,首先关闭了标准输出和错误输出那可以将标准输出重定向到标准输入exec1>&0是一种Shell命令行中的重定向语法,用于将标准输出(文件描述符1)重定向到标准输入(文件描述符0)。在LinuxShell中,每个进程都有三个默认的标准文件描述符:标准......