讲道理 我已经是个老年退役选手了 可惜被逼着去北大集训 水平本来就垫底结果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;
}