卷不动了(又名NOIP前的复健)

讲道理 我已经是个老年退役选手了 可惜被逼着去北大集训 水平本来就垫底结果NOI后还无训练 目标就是每天都不爆零就好了= = 主要是精英集训这群人太卷了 一个个都说不停课不训练 结果做的比集训队都多= = 为了显得我态(yi1)度(ran2)端(huo2)正(zhe) 就稍微写一点点集训队作业 主要是挑过的人多的做的 然后就是NOIP前还是稍微复健一下 因为CSP都一个月了 手确实有点生了(写数据结构都没那么快乐了)

Surveillance

考虑维护每个区间往右拓展的最远的下一个区间 那么建出来是个森林(因为要跨最后) 然后直接处理一下树上问题判断一下就好 我写的太丑了 细节全是一个一个点特判出来的

//Love and Freedom.
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
#define inf 20021225
#define N 1000100
#define pa pair<int,int>
using namespace std;
int read()
{
	int s=0,f=1; char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
	while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
	return f*s;
}
struct edge{int to,lt;}e[N]; int in[N],cnt,n,k,ans=inf; pa a[N];
void add(int x,int y){e[++cnt].to=y; e[cnt].lt=in[x]; in[x]=cnt;}
int cmp(int x,int y){int tx=a[x].first>a[x].second,ty=a[y].first>a[y].second; return tx^ty?(tx?x:y):(a[x].second<a[y].second?y:x);}
void dfs(int x,int wei,int len)
{
	if(a[x].first-1<=wei&&len>1)	return ans=min(ans,len),void();
	for(int i=in[x];i;i=e[i].lt)	dfs(e[i].to,wei,len+1);
}
bool ins(int x,int l,int r){return x>=l&&x<=r;}
bool sec(int x,int y)
{
	int tx=a[x].first>a[x].second,ty=a[y].first>a[y].second;
	if(tx^ty)	return a[x].second>=a[y].first-1; if(tx&ty)	return 1;
	return a[y].first<=a[x].second+1;
}
int main()
{
	n=read(),k=read(); for(int i=1;i<=k;i++) a[i].first=read(),a[i].second=read(); sort(a+1,a+k+1); int it=1,id=1;
	for(int i=1;i<=k;i++)	{while(it<=k&&sec(i,it))	id=cmp(id,it),it++; if(id!=i) add(id,i);}
	for(int i=1;i<=k;i++)	if(a[i].first>a[i].second)	ans=a[i].second==a[i].first-1?1:ans,dfs(i,a[i].second,1); else if(a[i].second==n)	ans=a[i].first==1?1:ans,dfs(i,0,1);
	if(ans==inf)	printf("impossible");
	else	printf("%d
",ans);
	return 0;
}

Intrinsic Interval

考虑合法区间的交和并显然都是合法的 那么离线下来以后对于当前点i作为区间右端点处理每个左端点左边最右的合法点就可以了 由于是排列 所以合法的$x,x+1$的二元组只有n-1个 就是跨过这两个点的区间可以+1(这是一个对于排列连续权值段的处理方法)合法点处理就是$val_l = r-l$ 维护$val_l+l$就可以了

//Love and Freedom.
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<set>
#include<vector>
#define ll long long
#define inf 20021225
#define N 200010
#define ls (x<<1)
#define rs (x<<1|1)
#define mid (l+r>>1)
#define pa pair<int,int>
using namespace std;
int read()
{
	int s=0,f=1; char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
	while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
	return f*s;
}
int mx[N<<2],tag[N<<2];
void puttag(int x,int t){mx[x]+=t,tag[x]+=t;}
void pushdown(int x){if(tag[x]) puttag(ls,tag[x]),puttag(rs,tag[x]),tag[x]=0;}
void pushup(int x){mx[x]=max(mx[ls],mx[rs]);}
void modify(int x,int l,int r,int LL,int RR,int v)
{
	if(l>=LL&&r<=RR)	return puttag(x,v); pushdown(x);
	if(LL<=mid)	modify(ls,l,mid,LL,RR,v);
	if(RR>mid)	modify(rs,mid+1,r,LL,RR,v);
	pushup(x);
}
int query(int x,int l,int r,int LL,int RR,int w)
{
	if(r>l)	pushdown(x);
	if(LL<=l&&RR>=r)
	{
		if(mx[x]<w)	return -1; if(l==r)	return l;
		return mx[rs]==w?query(rs,mid+1,r,LL,RR,w):query(ls,l,mid,LL,RR,w);
	}
	int wei=-1;
	if(RR>mid)	
	{
		wei=query(rs,mid+1,r,LL,RR,w);
		if(~wei)	return wei;
	}
	if(LL<=mid)	return query(ls,l,mid,LL,RR,w);
	return wei;
}
void build(int x,int l,int r)
{
	if(l==r)	return mx[x]=l,void();
	build(ls,l,mid),build(rs,mid+1,r); pushup(x);
}
set<pa> lpos; vector<pa> pos[N]; int n,m,a[N],lst[N],al[N],ar[N];
int main()
{
	n=read(); for(int i=1;i<=n;i++)	a[i]=read(); m=read(); build(1,1,n);
	int l,r; for(int i=1;i<=m;i++)	l=read(),r=read(),pos[r].push_back(make_pair(l,i));
	for(int i=1;i<=n;i++)
	{
		lst[a[i]]=i;
		if(a[i]>1&&lst[a[i]-1])	modify(1,1,n,1,lst[a[i]-1],1);
		if(a[i]<n&&lst[a[i]+1])	modify(1,1,n,1,lst[a[i]+1],1);
		for(int j=0;j<pos[i].size();j++)	lpos.insert(pos[i][j]);
		while(!lpos.empty())
		{
			pa wei=*(--lpos.end()); int qwq=query(1,1,n,1,wei.first,i);
			if(qwq==-1)	break; al[wei.second]=qwq; ar[wei.second]=i; lpos.erase(--lpos.end());
		}
	}
	for(int i=1;i<=m;i++)	printf("%d %d
",al[i],ar[i]);
	return 0;
}

Integral Polygons

垃圾题 拆成叉积和 显然只有奇偶的区别 讨论一下就好了

//Love and Freedom.
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
#define inf 20021225
#define N 200010
using namespace std;
int read()
{
	int s=0,f=1; char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
	while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
	return f*s;
}
struct poi{int x,y;}a[N]; int n,wei[N],pre[N][2][2][2];
int cross(poi a,poi b){return a.x*b.y+b.x*a.y;}
int main()
{
	n=read(); for(int i=1;i<=n;i++)	a[i].x=read()&1,a[i].y=read()&1;
	for(int i=1;i<=n;i++)	wei[i]=(wei[i-1]+cross(a[i-1?i-1:n],a[i]))&1; ll ans=0;
	for(int i=1;i<=n;i++)
	{
		for(int s=0;s<2;s++)	for(int x=0;x<2;x++)	for(int y=0;y<2;y++)
			if(!((a[i].x*y+a[i].y*x-s+wei[i])&1))	ans+=pre[i-1][s][x][y];
		for(int s=0;s<2;s++)	for(int x=0;x<2;x++)	for(int y=0;y<2;y++)
			pre[i][s][x][y]=pre[i-1][s][x][y];
		pre[i][wei[i]][a[i].x][a[i].y]++;
	}
	if(wei[n])	puts("0"); else printf("%lld
",ans-n);
	return 0;
}

### Hack Protection
果然还是数据结构比较快乐 对于每个左端点显然&的值变化只有O(log)个 然后看区间内有无异或满足即可
//Love and Freedom.
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<set>
#include<map>
#include<vector>
#define ll long long
#define inf 20021225
#define N 100010
#define pa pair<int,int>
using namespace std;
int read()
{
	int s=0,f=1; char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
	while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
	return f*s;
}
int n,a[N],pre[N],nmd[N][32]; pa nxt[32]; set<int> ze[32]; map<int,vector<int> > w;
int main()
{
	n=read(); for(int i=1;i<=n;i++)	pre[i]=pre[i-1]^(a[i]=read()),w[pre[i]].push_back(i);
	for(int i=n;i;i--)	for(int b=0;b<31;b++)	if(!(a[i]>>b&1))	nmd[i][b]=i; else nmd[i][b]=nmd[i+1][b];
	ll ans=0;
	for(int i=1;i<=n;i++)
	{
		int tot=0,val=2147483647; 
		for(int b=0;b<31;b++)
			if(nmd[i][b])	nxt[++tot]=make_pair(nmd[i][b],b);
		sort(nxt+1,nxt+tot+1); int lst=i;
		for(int k=1,j;k<=tot;k=j)
		{
			int pos=nxt[k].first,qwq=val^pre[i-1];
			if(w.find(qwq)!=w.end())
			{
				vector<int>::iterator bg=w[qwq].begin(),ed=w[qwq].end();
				ans+=lower_bound(bg,ed,pos)-lower_bound(bg,ed,lst);
			}
			for(j=k;j<=tot&&nxt[j].first==nxt[k].first;j++) val^=1<<nxt[j].second; lst=pos;
		}
		int qwq=val^pre[i-1];
		if(w.find(qwq)!=w.end())
		{
			vector<int>::iterator bg=w[qwq].begin(),ed=w[qwq].end();
			ans+=lower_bound(bg,ed,n+1)-lower_bound(bg,ed,lst);
		}
	}
	printf("%lld
",ans);
	return 0;
}

The Imp

博弈论题 有一个不是很显然的结论就是每次取的价值是单调不降的 然后就可以直接dp了= =

//Love and Freedom.
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
#define inf 20021225
#define N 200010
using namespace std;
int read()
{
	int s=0,f=1; char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
	while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
	return f*s;
}
int n,k,f[N][10]; pair<int,int> w[N];
int main()
{
	int t=read();
	while(t--)
	{
		n=read(),k=read(); for(int i=1;i<=n;i++)	w[i].first=read(),w[i].second=read(); sort(w+1,w+n+1); reverse(w+1,w+n+1);
		for(int i=1;i<=n;i++)	f[i][0]=max(f[i-1][0],w[i].first-w[i].second);
		for(int i=1;i<=n;i++)	for(int j=1;j<=k;j++)	f[i][j]=max(f[i-1][j],min(w[i].first-w[i].second,f[i-1][j-1]-w[i].second));
		printf("%d
",f[n][k]);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/hanyuweining/p/14070828.html