[考试总结]noip模拟31

三个 XIN 算法就打上去了,其他真的啥思路都没有。

然后期望得分实际上就是 \(\color{red}0\)

然而战神还是一场至少一个正解,然后沈队只交一个代码,然而 \(\color{green}{AC}\)

然后这个题目的答案大小还是很简单,然而就是这个sb字典序难搞。。。

然后第二题直接(学长skyh语录)冲上一个 XIN 队,然后 \(n^n\),然而理论上一个点都过不了。。。

然后认为自己的 \(T3\) 能水上 \(25pts\),然而谁知道出题人不是人,上来 \(m \leq 10\) ,然而 \(n \leq 1000000\)

然后抱 \(\color{red}0\)

生气。。。。。。。。。。。

Game

我们首先可以很快地算出答案。

我们建一颗 权值线段树 来维护答案,然后建完树的 \(t[1].s\) 就已经是那个长度的答案了。

之后我们开始考虑 二分答案,每次删去一个节点进行尝试,之后查看答案是否变化,如果不变化,则可行。

重复这样的操作,记录答案。

然后 \(std\) 上的 \(multiset\) 完全没有必要,一个桶解决。

然后这个题目的线段树可以 \(zkw\),然后快一倍!!!!!

然而我没打。。。



#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register signed i=a;i<=b;++i)
#define throw(i,a,b) for(register signed i=a;i>=b;--i)
#define asm(i,x) for(register signed i=head[x];i;i=edge[i].next)
namespace xin_io
{
	#define debug cout<<"debug"<<endl
	#define enum(x) cout<<#x" = "<<x<<endl
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
	char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
	class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &x)
	{
		register type s = 0; register int f = 1; register char ch = gc();
		while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch  xor 48),ch = gc(); return x = s * f,*this;
	}}io;
}
using namespace xin_io; static const int maxn = 1e6+10,inf = 1e9+7,mod = 998244353; const ll llinf = 1e18+7;
namespace xin
{
	class xin_segment
	{
		protected:
			#define ls(fa) (fa << 1)
			#define rs(fa) (fa << 1 | 1)
			inline void up(int fa)
			{
				register int temp = std::min(t[rs(fa)].s1,t[ls(fa)].s2);
				t[fa].s = t[ls(fa)].s + t[rs(fa)].s + temp;
				t[fa].s1 = t[ls(fa)].s1 + t[rs(fa)].s1 - temp;
				t[fa].s2 = t[ls(fa)].s2 + t[rs(fa)].s2 - temp;
			}
		public:	
			class xin_tree{public:int s,s1,s2;}t[maxn];
			void modify(int fa,int l,int r,int pos,int val1,int val2)
			{
				if(l == r) return t[fa].s1 += val1,t[fa].s2 += val2,void();
				register int mid = l + r >> 1;
				if(pos <= mid) modify(ls(fa),l,mid,pos,val1,val2); 	
				else modify(rs(fa),mid+1,r,pos,val1,val2);
				up(fa);
			}
	}t;
	int a[maxn],b[maxn],n;
	int maxx = -inf;
	int ton[maxn];
	inline short main()
	{
		io >> n;
		try(i,1,n) io >> a[i],maxx = std::max(maxx,a[i]);
		try(i,1,n) io >> b[i],ton[b[i]]++,maxx = std::max(maxx,b[i]),ton[0] = std::max(ton[0],b[i]);
		try(i,1,n) t.modify(1,1,maxx,a[i],0,1),t.modify(1,1,maxx,b[i],1,0);
		int ans = t.t[1].s;
		try(i,1,n)
		{
			t.modify(1,1,maxx,a[i],0,-1);
			register int l = a[i] + 1,r = ton[0]; while(!ton[ton[0]]) r = --ton[0];
			while(l < r)
			{
				register int mid = (l + r + 1) >> 1;
				t.modify(1,1,maxx,mid,-1,0);
				if(ans - 1 == t.t[1].s) l = mid; else r = mid - 1;
				t.modify(1,1,maxx,mid,1,0);
			}
			t.modify(1,1,maxx,l,-1,0);
			if(l <= r and ans - 1 == t.t[1].s) printf("%d ",l),ans--,ton[l]--;
			else
			{
				t.modify(1,1,maxx,l,1,0);
				l = 1; r = a[i];
				while(l < r)
				{
					register int mid = ( l + r + 1) >> 1;
					t.modify(1,1,maxx,mid,-1,0);
					if(ans == t.t[1].s) l = mid; else r = mid - 1;
					t.modify(1,1,maxx,mid,1,0);
				}
				t.modify(1,1,maxx,l,-1,0);
				printf("%d ",l);
				ton[l]--;
			}
		}
		return 0;
	}
}
signed main() {return xin::main();}

Time

我们找到最小值,然后向左或者向右放,当然要找近的。

重复这个过程。

就这??????

就这。。

然后距离可以 树状数组,然后可以 \(deque\)



#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register signed i=a;i<=b;++i)
#define throw(i,a,b) for(register signed i=a;i>=b;--i)
#define asm(i,x) for(register signed i=head[x];i;i=edge[i].next)
namespace xin_io
{
	#define enum(x) cout<<#x" = "<<x<<endl;
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
	char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
	class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &x)
	{
		register type s = 0; register int f = 1; register char ch = gc();
		while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch  xor 48),ch = gc(); return x = s * f,*this;
	}}io;
}
#define int long long
using namespace xin_io; static const int maxn = 1e6+10,inf = 1e9+7,mod = 998244353; const ll llinf = 1e18+7;
namespace xin
{
	int n;
	class xin_bit
	{
		protected:
			#define lowbit(i) (i & -i)
		public:
			int c[maxn];
			inline void add(int x,int val) {for(register int i=x;i<=n;i+=lowbit(i)) c[i] += val;}
			inline int  query(int x) {int ret = 0;for(register int i=x;i;i-=lowbit(i)) ret += c[i]; return ret;}
	}bit;
	std::deque<int>q[maxn / 10];
	int maxx = -inf,ans = 0;
	inline short main()
	{
		io >> n;
		try(i,1,n)
		{
			register int x;  io >> x; maxx = std::max(maxx,x);
			q[x].push_back(i); bit.add(i,1);
		}
		try(i,1,maxx)
		while(!q[i].empty())
		{
			register int x = q[i].front(),a =  bit.query(x-1),y = q[i].back(),b = bit.query(n) - bit.query(y);
			if(a < b) ans += a,bit.add(x,-1),q[i].pop_front();
			else ans += b,bit.add(y,-1),q[i].pop_back();
		}
		cout<<ans<<endl;
		return 0;
	}
}
signed main() {return xin::main();}

Cover

子区间之间只有相互包含和不交的关系,因此它们的包含关系会构成一棵树

然后就是 树形 dp

然后我们维护一个 差分表

\(STL\)还是要用上。



#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register signed i=a;i<=b;++i)
#define throw(i,a,b) for(register signed i=a;i>=b;--i)
#define asm(i,x) for(register signed i=head[x];i;i=edge[i].next)
namespace xin_io
{
	#define debug cout<<"debug"<<endl
	#define enum(x) cout<<#x" = "<<x<<endl;
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
	char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
	class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &x)
	{
		x = 0; register int f = 0; register char ch = gc();
		while(!isdigit(ch)) {f|=ch=='-'; ch = gc();}
		while( isdigit(ch)) x = (x << 1) + (x << 3) + (ch  xor 48),ch = gc(); return x = f ? -x : x,*this;
	}}io;
}
//#define int long long 
using namespace xin_io; static const int maxn = 3e5+10,inf = 1e9+7,mod = 998244353; const ll llinf = 1e18+7;
namespace xin
{
	class xin_data
	{
		private:
			friend bool operator < (xin_data x,xin_data y)
			{return x.l == y.l ? x.r > y.r : x.l < y.l;}
		public:
			int l,r,a;
	}d[maxn];
	int n;
	int st[maxn];
	std::vector<int>vec[maxn];
	std::multiset<ll>mt[maxn];
	int jsq1,jsq2;
	inline void merge(std::multiset<ll>&a,std::multiset<ll>&b)
	{
		if(a.size() < b.size()) std::swap(a,b);
		std::vector<ll>temp;
		for(auto i : b) temp.push_back(i + *a.begin()),a.erase(a.begin());
		for(auto i : temp) a.insert(i);
	}
	void dfs(int x)
	{


		for(auto v : vec[x])
		{
			dfs(v);
			merge(mt[x],mt[v]);
		}
		mt[x].insert(-d[x].a);
	}
	inline short main()
	{
		io >> n >> n;
		try(i,1,n) io >> d[i].l >> d[i].r >> d[i].a;
		st[++st[0]] = 0; std::sort(d+1,d+n+1);
		try(i,1,n)
		{
			while(st[st[0]] and d[st[st[0]]].r < d[i].r) st[0]--;
//			cout<<++jsq1<<" st[st[0]] = "<<st[st[0]]<<endl;
			vec[st[st[0]]].push_back(i);
//			cout<<++jsq2<<" st[st[0]] = "<<st[st[0]]<<endl;
			st[++st[0]] = i;
		}
		dfs(0); ll ans = 0;
		try(i,1,n)
		{
			if(mt[0].size())
			{
				ans -= *mt[0].begin();
				mt[0].erase(mt[0].begin());	
			}
			printf("%lld ",ans);
		}
		return 0;
	}
}
signed main() {return xin::main();}
posted @ 2021-08-06 19:17  NP2Z  阅读(43)  评论(1编辑  收藏  举报