noip63

T1

考场想法:模了几组样例发现,这样的电线应该满足在奇环中,并且这条边的两个端点之间没有重边,再模了几组发现只在奇环不行,然后就不会了,丢了个bfs跑路了。

其实离正解很近了,就差个偶环了。。。

30pts:枚举每一条可行的边,然后bfs检验。然而重测删了个点,成26pts了QAQ

100pts:

先把题解里的转换题意说一下。

first:实际上是让找一条边,使得删去这条边之后的图为一个二分图,并且删掉边的两个端点不在同一部中。

second:说的再简单一点就是找有多少条边满足图中所有的奇环都包含该边,并且该边不在偶环中。

这样的话,就比较简单了。

具体实现可以考虑dfs树。

\(bel_{i}\) 表示编号为 \(i\) 的边属于多少个奇环, \(odd\) 为图中所有奇环的数量,再开个差分数组 \(delta\) ,然后通过dfs找奇环,当搜到一个环时,设当前边为 \((u,v)\) ,如果为奇环则 \(bel_{i}++,bel_{i^1}++,delta_{v}--,odd++\) ,否则 \(bel_{i}--,bel_{i^1}--,delta_{v}++\) ,dfs回溯的时候再更新一下 \(delta\)\(bel\)

最后判断一下 \(bel_{i}\) 是否等于 \(odd\) 即可。

Code
#include<cstdio>
#include<cctype>
#include<functional>
#define MAX 100003
#define re register
using std::function;
namespace some
{
	struct stream
	{
		template<typename type>inline stream &operator >>(type &s)
		{
			bool w=0; s=0; char ch=getchar();
			while(!isdigit(ch)){ w|=ch=='-'; ch=getchar(); }
			while(isdigit(ch)){ s=(s<<1)+(s<<3)+(ch^48); ch=getchar(); }
			return s=w?-s:s,*this;
		}
	}cin;
}using namespace some;
namespace Graph
{
	struct graph
	{
		int next;
		int to;
	}edge[MAX<<2];
	int cnt=1,head[MAX];
	auto add = [](int u,int v) -> void { edge[++cnt] = (graph){head[u],v},head[u] = cnt; };
	bool vis[MAX<<2];
	int dep[MAX],odd,bel[MAX<<2],delta[MAX];
	function<void(int,int)> dfs = [](int u,int depth) -> void
	{
		dep[u] = depth;
		for(re int i=head[u],v,dis; i; i=edge[i].next)
		{
			if(vis[i])
			{ continue ; }
			v = edge[i].to,vis[i] = vis[i^1] = true;
			if(dep[v])
			{
				dis = dep[u]-dep[v]+1;
				if(dis&1)
				{ bel[i]++,bel[i^1]++,delta[v]--,odd++; }
				else
				{ bel[i]--,bel[i^1]--,delta[v]++; }
				delta[u] += bel[i];
			}
			else
			{
				dfs(v,depth+1);
				delta[u] += delta[v];
				bel[i] = bel[i^1] = delta[v];
			}
		}
	};
}using namespace Graph;
namespace OMA
{
	int n,m,ans;
	auto main = []() -> signed
	{
		freopen("a.in","r",stdin); freopen("a.out","w",stdout);
		cin >> n >> m;
		for(re int i=1,u,v; i<=m; i++)
		{ cin >> u >> v; add(u,v),add(v,u); }
		dfs(1,1);
		for(re int i=2; i<=cnt; i+=2)
		{ if(bel[i]==odd){ ans++; } }
		printf("%d\n",ans);
		return 0;
	};
}
signed main()
{ return OMA::main(); }

T2

考场想法:不会,写暴力吧,枚举每一个区间,再枚举一下交换方案数。然而写不出来....又去读了读题,啊,有无解情况,好耶!于是输出-1走人了。

有15pts

不是子任务,所以骗到了分....

其实特殊性质还是挺可做的,然而还有2h结束,干脆跑路了。

Code
咕咕咕

T3

考场想法:并不太会,想24分治来着,然而这个想法马上就被否掉了,想了想,发现啥也想不出来,于是丢枚举暴力走人了。

24分治能A???还是太菜了...

25pts:\(n\le 500\) 的点,直接枚举即可。

91pts:照题解说的做个前缀和即可。

100pts:

并没有打正解,上了Varuxn的贼船,对于12种情况分类讨论(另外12种通过 \(reverse\) 操作就转换成同一种了),用线段树维护即可。

具体实现建议直接看code。

Code
#include<cstdio>
#include<cctype>
#include<algorithm>
#define MAX 2003
#define re register
#define int64_t long long
using std::reverse;
namespace some
{
	struct stream
	{
		template<typename type>inline stream &operator >>(type &s)
		{
			bool w=0; s=0; char ch=getchar();
			while(!isdigit(ch)){ w|=ch=='-'; ch=getchar(); }
			while(isdigit(ch)){ s=(s<<1)+(s<<3)+(ch^48); ch=getchar(); }
			return s=w?-s:s,*this;
		}
	}cin;
	int64_t ans;
	int n,a[5],b[MAX];
}using namespace some;
namespace Segment_TREE
{
	struct Segment_Tree
	{
		int sum[MAX<<2];
		#define ls(p) p<<1
		#define rs(p) p<<1|1
		#define mid (l+r>>1)
		#define Push_up(p) { sum[p] = sum[ls(p)]+sum[rs(p)]; }
		void build(int p,int l,int r)
		{
			if(l==r)
			{ sum[p] = 0; return ; }
			sum[p] = 0;
			build(ls(p),l,mid),build(rs(p),mid+1,r);
		}
		void insert(int p,int l,int r,int pos,int val)
		{
			if(l==r)
			{ sum[p] += val; return ; }
			if(pos<=mid)
			{ insert(ls(p),l,mid,pos,val); }
			else
			{ insert(rs(p),mid+1,r,pos,val); }
			Push_up(p);
		}
		int query(int p,int l,int r,int lp,int rp,int tot = 0)
		{
			if(lp>rp)
			{ return 0; }
			if(lp<=l&&r<=rp)
			{ return sum[p]; }
			if(lp<=mid)
			{ tot += query(ls(p),l,mid,lp,rp); }
			if(rp>mid)
			{ tot += query(rs(p),mid+1,r,lp,rp); }
			return tot;
		}
	}st1,st2;
}using namespace Segment_TREE;
namespace divide_data_and_solve
{
	auto task1_24 = []() -> void // ok
	{
		for(re int i=4; i<=n; i++)
		{
			st1.build(1,1,n),st1.insert(1,1,n,b[1],1),st2.build(1,1,n);
			for(re int j=2; j<=i-1; j++) { st2.insert(1,1,n,b[j],1); }
			for(re int j=2; j<=i-2; j++) { st2.insert(1,1,n,b[j],-1),ans += st1.query(1,1,n,1,b[j]-1)*st2.query(1,1,n,b[j]+1,b[i]-1),st1.insert(1,1,n,b[j],1); }
		}
	}; // 1,2,3,4 and 4,3,2,1
	auto task2_18 = []() -> void // ok
	{
		for(re int i=4; i<=n; i++)
		{
			st1.build(1,1,n),st1.insert(1,1,n,b[1],1),st2.build(1,1,n);
			for(re int j=2; j<=i-1; j++) { st2.insert(1,1,n,b[j],1); }
			for(re int j=2; j<=i-2; j++) { st2.insert(1,1,n,b[j],-1); if(b[j]<b[i]){ ans += st1.query(1,1,n,1,b[j]-1)*st2.query(1,1,n,b[i]+1,n); } st1.insert(1,1,n,b[j],1); }
		}
	}; // 1,2,4,3 and 3,4,2,1
	auto task3_22 = []() -> void // ok
	{
		for(re int i=3; i<=n-1; i++)
		{
			st1.build(1,1,n),st1.insert(1,1,n,b[1],1),st2.build(1,1,n);
			for(re int j=i+1; j<=n; j++) { st2.insert(1,1,n,b[j],1); }
			for(re int j=2; j<=i-1; j++) { if(b[j]>b[i]) { ans += st1.query(1,1,n,1,b[i]-1)*st2.query(1,1,n,b[j]+1,n); } st1.insert(1,1,n,b[j],1); }
		}
	}; // 1,3,2,4 and 4,2,3,1
	auto task4_12 = []() -> void // ok
	{
		for(re int i=4; i<=n; i++)
		{
			st1.build(1,1,n),st1.insert(1,1,n,b[1],1),st2.build(1,1,n);
			for(re int j=2; j<=i-1; j++) { st2.insert(1,1,n,b[j],1); }
			for(re int j=2; j<=i-2; j++) { st2.insert(1,1,n,b[j],-1); if(b[j]>b[i]) { ans += st1.query(1,1,n,1,b[i]-1)*st2.query(1,1,n,b[j]+1,n); } st1.insert(1,1,n,b[j],1); }
		}
	}; // 1,3,4,2 and 2 4 3 1
	auto task5_16 = []() -> void // ok
	{
		for(re int i=3; i<=n-1; i++)
		{
			st1.build(1,1,n),st1.insert(1,1,n,b[1],1),st2.build(1,1,n);
			for(re int j=i+1; j<=n; j++) { st2.insert(1,1,n,b[j],1); }
			for(re int j=2; j<=i-1; j++) { if(b[j]>b[i]){ ans += st1.query(1,1,n,1,b[i]-1)*st2.query(1,1,n,b[i]+1,b[j]-1); } st1.insert(1,1,n,b[j],1); }
		}
	}; // 1,4,2,3 and 3,2,4,1
	auto task6_10 = []() -> void // ok
	{
		for(re int i=4; i<=n; i++)
		{
			st1.build(1,1,n),st1.insert(1,1,n,b[1],1),st2.build(1,1,n);
			for(re int j=2; j<=i-1; j++) { st2.insert(1,1,n,b[j],1); }
			for(re int j=2; j<=i-2; j++) { st2.insert(1,1,n,b[j],-1),ans += st1.query(1,1,n,1,b[i]-1)*st2.query(1,1,n,b[i]+1,b[j]-1),st1.insert(1,1,n,b[j],1); }
		}
	}; // 1,4,3,2 and 2,3,4,1
	auto task7_23 = []() -> void // ok
	{
		for(re int i=3; i<=n-1; i++)
		{
			st1.build(1,1,n),st1.insert(1,1,n,b[1],1),st2.build(1,1,n);
			for(re int j=i+1; j<=n; j++) { st2.insert(1,1,n,b[j],1); }
			for(re int j=2; j<=i-1; j++) { if(b[j]<b[i]) { ans += st1.query(1,1,n,b[j]+1,b[i]-1)*st2.query(1,1,n,b[i]+1,n); } st1.insert(1,1,n,b[j],1); }
		}
	}; // 2,1,3,4 and 4,3,1,2
	auto task8_17 = []() -> void // ok
	{
		for(re int i=4; i<=n; i++)
		{
			st1.build(1,1,n),st1.insert(1,1,n,b[1],1),st2.build(1,1,n);
			for(re int j=2; j<=i-1; j++) { st2.insert(1,1,n,b[j],1); }
			for(re int j=2; j<=i-2; j++) { st2.insert(1,1,n,b[j],-1),ans += st1.query(1,1,n,b[i]+1,b[j]-1)*st2.query(1,1,n,1,b[i]-1),st1.insert(1,1,n,b[j],1); }
		}
	}; // 2,1,4,3 and 3,4,1,2
	auto task9_20 = []() -> void // ok
	{
		for(re int i=3; i<=n-1; i++)
		{
			st1.build(1,1,n),st1.insert(1,1,n,b[1],1),st2.build(1,1,n);
			for(re int j=i+1; j<=n; j++) { st2.insert(1,1,n,b[j],1); }
			for(re int j=2; j<=i-1; j++) { if(b[j]>b[i]){ ans += st1.query(1,1,n,b[i]+1,b[j]-1)*st2.query(1,1,n,b[j]+1,n); } st1.insert(1,1,n,b[j],1); }
		}
	}; // 2,3,1,4 and 4,1,3,2
	auto task11_14 = []() -> void // ok
	{
		for(re int i=4,sum; i<=n; i++)
		{
			st1.build(1,1,n),st2.build(1,1,n),sum = 0;
			for(re int j=1; j<=i-1; j++) { st2.insert(1,1,n,b[j],1); }
			for(re int j=1; j<=i-2; j++) { if(b[j]>b[i]) { ans += sum; } else { sum -= st1.query(1,1,n,b[j]+1,n),sum += st2.query(1,1,n,1,b[j]-1); st2.insert(1,1,n,b[j],-1),st1.insert(1,1,n,b[j],1); } }
		}
	}; // 2,4,1,3 and 3,1,4,2
	auto task13_21 = []() -> void // ok
	{
		for(re int i=3; i<=n-1; i++)
		{
			st1.build(1,1,n),st2.build(1,1,n);
			for(re int j=1; j<=i-1; j++) { st1.insert(1,1,n,b[j],1); }
			for(re int j=i+1; j<=n; j++) { st2.insert(1,1,n,b[j],1); }
			for(re int j=1; j<=i-2; j++) { st1.insert(1,1,n,b[j],-1); if(b[j]>b[i]) { ans += st1.query(1,1,n,1,b[i]-1)*st2.query(1,1,n,b[j]+1,n); } }
		}
	}; // 3,1,2,4 and 4,2,1,3
	auto task15_19 = []() -> void // ok
	{
		for(re int i=4; i<=n; i++)
		{
			st1.build(1,1,n),st1.insert(1,1,n,b[1],1),st2.build(1,1,n);
			for(re int j=2; j<=i-1; j++) { st2.insert(1,1,n,b[j],1); }
			for(re int j=2; j<=i-2; j++) { st2.insert(1,1,n,b[j],-1),ans += st1.query(1,1,n,b[j]+1,b[i]-1)*st2.query(1,1,n,1,b[j]-1),st1.insert(1,1,n,b[j],1); }
		}
	}; // 3,2,1,4 and 4,1,2,3
}using namespace divide_data_and_solve;
namespace OMA
{
	auto main = []() -> signed
	{
		freopen("c.in","r",stdin); freopen("c.out","w",stdout);
		cin >> n;
		for(re int i=1; i<=4; i++) { cin >> a[i]; }
		for(re int i=1; i<=n; i++) { cin >> b[i]; }
		if(a[1]==1&&a[2]==2&&a[3]==3&&a[4]==4) { task1_24(); } // 1
		if(a[1]==4&&a[2]==3&&a[3]==2&&a[4]==1) { reverse(b+1,b+1+n); task1_24(); } // 24
		if(a[1]==1&&a[2]==2&&a[3]==4&&a[4]==3) { task2_18(); } // 2
		if(a[1]==3&&a[2]==4&&a[3]==2&&a[4]==1) { reverse(b+1,b+1+n); task2_18(); } // 18
		if(a[1]==1&&a[2]==3&&a[3]==2&&a[4]==4) { task3_22(); } // 3
		if(a[1]==4&&a[2]==2&&a[3]==3&&a[4]==1) { reverse(b+1,b+1+n); task3_22(); } // 22
		if(a[1]==1&&a[2]==3&&a[3]==4&&a[4]==2) { task4_12(); } // 4
		if(a[1]==2&&a[2]==4&&a[3]==3&&a[4]==1) { reverse(b+1,b+1+n); task4_12(); } // 12
		if(a[1]==1&&a[2]==4&&a[3]==2&&a[4]==3) { task5_16(); } // 5
		if(a[1]==3&&a[2]==2&&a[3]==4&&a[4]==1) { reverse(b+1,b+1+n); task5_16(); } // 16
		if(a[1]==1&&a[2]==4&&a[3]==3&&a[4]==2) { task6_10(); } // 6
		if(a[1]==2&&a[2]==3&&a[3]==4&&a[4]==1) { reverse(b+1,b+1+n); task6_10(); } // 10
		if(a[1]==2&&a[2]==1&&a[3]==3&&a[4]==4) { task7_23(); } // 7
		if(a[1]==4&&a[2]==3&&a[3]==1&&a[4]==2) { reverse(b+1,b+1+n); task7_23(); } // 23
		if(a[1]==3&&a[2]==4&&a[3]==1&&a[4]==2) { task8_17(); } // 17
		if(a[1]==2&&a[2]==1&&a[3]==4&&a[4]==3) { reverse(b+1,b+1+n); task8_17(); } // 8
		if(a[1]==2&&a[2]==3&&a[3]==1&&a[4]==4) { task9_20(); } // 9
		if(a[1]==4&&a[2]==1&&a[3]==3&&a[4]==2) { reverse(b+1,b+1+n); task9_20(); } // 20
		if(a[1]==2&&a[2]==4&&a[3]==1&&a[4]==3) { task11_14(); } // 11
		if(a[1]==3&&a[2]==1&&a[3]==4&&a[4]==2) { reverse(b+1,b+1+n); task11_14(); } // 14
		if(a[1]==3&&a[2]==1&&a[3]==2&&a[4]==4) { task13_21(); } // 13
		if(a[1]==4&&a[2]==2&&a[3]==1&&a[4]==3) { reverse(b+1,b+1+n); task13_21(); } // 21
		if(a[1]==3&&a[2]==2&&a[3]==1&&a[4]==4) { task15_19(); } // 15
		if(a[1]==4&&a[2]==1&&a[3]==2&&a[4]==3) { reverse(b+1,b+1+n); task15_19(); } // 19
		printf("%lld\n",ans);
		return 0;
	};
}
signed main()
{ return OMA::main(); }

大部分是复制粘贴,要改的地方不算多。

不过话说回来考场还真有巨佬打出来这种题....果然还是菜了。

T4

考场想法:啥也没想出来,干脆直接搜,用dp检验。

数据一开始错了,改后有20pts....

Code
咕咕咕
posted @ 2021-09-27 21:40  -OMA-  阅读(71)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end