等到晚上应该可以更新当日题解。
D1T1
设DP状态 f [ i ] [ 0 / 1 ] [ j ] f[i][0/1][j] f[i][0/1][j]表示前 i i i个数字,总共有 j j j个选择了A,上一个选择了A/B是否合法,直接暴力复杂度 O ( n 2 ) O(n^2) O(n2)。
观察性质,可以证明对于每个 i i i,其合法的肯定为一个连续段。证明略。
因此转移只需要记录左右端点。复杂度 O ( n ) O(n) O(n)
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned ll
#define uint unsigned
#define pii pair<int,int>
#define pll pair<ll,ll>
#define IT iterator
#define PB push_back
#define fi first
#define se second
#define For(i,j,k) for (int i=(int)(j);i<=(int)(k);i++)
#define Rep(i,j,k) for (int i=(int)(j);i>=(int)(k);i--)
#define CLR(a,v) memset(a,v,sizeof(a));
#define CPY(a,b) memcpy(a,b,sizeof(a));
#define debug puts("wzpakking")
#define y1 ysghysgsygsh
using namespace std;
const int INF=1<<30;
const int N=1000005;
int n,a[N],b[N];
pii f[N][2];
char ans[N];
void upd(pii &x,pii y){
x.fi=min(x.fi,y.fi);
x.se=max(x.se,y.se);
}
int main(){
scanf("%d",&n);
For(i,1,2*n) scanf("%d",&a[i]);
For(i,1,2*n) scanf("%d",&b[i]);
f[0][0]=f[0][1]=pii(0,0);
For(i,1,2*n){
f[i][0]=f[i][1]=pii(INF,-INF);
if (a[i-1]<=a[i]) upd(f[i][0],f[i-1][0]);
if (b[i-1]<=a[i]) upd(f[i][0],f[i-1][1]);
if (a[i-1]<=b[i]) upd(f[i][1],f[i-1][0]);
if (b[i-1]<=b[i]) upd(f[i][1],f[i-1][1]);
++f[i][1].fi; ++f[i][1].se;
}
int fl=-1,rem=n;
For(i,0,1)
if (f[2*n][i].fi<=n&&n<=f[2*n][i].se)
fl=i;
if (fl==-1)
return puts("-1"),0;
Rep(i,2*n,1){
ans[i]=(fl?'B':'A');
rem-=fl;
int v=(fl?b[i]:a[i]);
if (a[i-1]<=v&&f[i-1][0].fi<=rem&&rem<=f[i-1][0].se) fl=0;
else assert(b[i-1]<=v&&f[i-1][1].fi<=rem&&rem<=f[i-1][1].se),fl=1;
}
printf("%s\n",ans+1);
}
D1T2
设所有正方形的右边界最小值为 m n x mnx mnx。
则可以证明若有解一定存在一个竹签使得其横坐标为 m n x mnx mnx。即同可以调整坐标得到一个不劣的方案。
类似的我们求出正方形的左边界最大值,上边界最小值,下边界最大值。类似的也可以证明若有解一定存在一个竹签使得其在直线上。
对于 K ≤ 3 K \leq 3 K≤3的情况,根据鸽巢原理在解一定会选择两条直线的交点,因此直接爆搜即可,时间复杂度 O ( n × 4 K ) O(n \times 4^K) O(n×4K)。
对于 K = 4 K=4 K=4的情况,若一个矩形和三条限制直线相交,此时我们可以忽略这个矩形,因为任意解均会覆盖到这个矩形。
剩下最多只有两条边被覆盖,考虑2-sat模型,表示每个矩形被哪一条边覆盖。限制条件为若两个区间不存在交,则一定不能同时被这一条边覆盖。
利用数据结构或排序来优化2-sat建边即可。
时间复杂度 O ( n ( log n + 4 K ) ) O(n(\log n+4^K)) O(n(logn+4K))
代码在路上。
UPD:代码来了!
如果这份代码有bug请联系博主(
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned ll
#define uint unsigned
#define pii pair<int,int>
#define pll pair<ll,ll>
#define IT iterator
#define PB push_back
#define fi first
#define se second
#define For(i,j,k) for (int i=(int)(j);i<=(int)(k);i++)
#define Rep(i,j,k) for (int i=(int)(j);i>=(int)(k);i--)
#define CLR(a,v) memset(a,v,sizeof(a));
#define CPY(a,b) memcpy(a,b,sizeof(a));
#define debug puts("wzpakking")
#define y1 ysghysgsygsh
using namespace std;
const int N=200005;
struct rect{
int x1,y1,x2,y2;
void init(){
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
}
}a[N];
pii ans[10];
int n,K,cnt[N];
void axiba(int x,int y,int v){
For(i,1,n)
if (a[i].x1<=x&&x<=a[i].x2)
if (a[i].y1<=y&&y<=a[i].y2)
cnt[i]+=v;
}
void dfs(int d){
int mnx=1e9,mxx=1;
int mny=1e9,mxy=1;
For(i,1,n) if (!cnt[i]){
mnx=min(mnx,a[i].x2);
mxx=max(mxx,a[i].x1);
mny=min(mny,a[i].y2);
mxy=max(mxy,a[i].y1);
}
if (d==1){
if (mxx<=mnx&&mxy<=mny){
ans[1]=pii(mnx,mny);
For(i,1,K) printf("%d %d\n",ans[i].fi,ans[i].se);
exit(0);
}
return;
}
For(fx,0,1) For(fy,0,1){
int px=(fx?mxx:mnx);
int py=(fy?mny:mxy);
axiba(px,py,1);
ans[d]=pii(px,py);
dfs(d-1);
axiba(px,py,-1);
}
}
struct node{
int x,v0,v1;
bool operator <(const node &a)const{
return x<a.x;
}
};
namespace solver2{
const int M=N*20;
vector<int> e[M];
int dfn[M],low[M],nd;
int vis[M],stk[M],be[M];
void tarjan(int x){
dfn[x]=low[x]=++*dfn;
stk[++*stk]=x; vis[x]=1;
for (auto i:e[x])
if (!dfn[i]){
tarjan(i);
low[x]=min(low[x],low[i]);
}
else if (vis[i])
low[x]=min(low[x],dfn[i]);
if (low[x]==dfn[x]){
++*be;
int y=19260817;
for (;y!=x;){
y=stk[(*stk)--];
vis[y]=0; be[y]=*be;
}
}
}
void add(int x,int y){
//cout<<x<<' '<<y<<endl;
if (!x||!y) return;
//cout<<x<<' '<<y<<endl;
e[x].PB(y);
}
int pr[N],su[N];
int id[N][2],at[N][2];
vector<node> vl[10],vr[10];
void build(int id){
if (!vl[id].size()) return;
int sz=vl[id].size(),pos=0;
sort(vl[id].begin(),vl[id].end());
sort(vr[id].begin(),vr[id].end());
pr[0]=su[sz+1]=0;
For(i,1,sz){
pr[i]=++nd;
add(pr[i-1],pr[i]);
add(vr[id][i-1].v0,pr[i]);
}
Rep(i,sz,1){
su[i]=++nd;
add(su[i],su[i+1]);
add(su[i],vl[id][i-1].v1);
}
pos=0;
For(i,0,sz-1){
for (;pos!=sz&&vr[id][i].x>=vl[id][pos].x;++pos);
add(pr[i+1],su[pos+1]);
}
//partA
Rep(i,sz,1){
su[i]=++nd;
add(su[i+1],su[i]);
add(vl[id][i-1].v0,su[i]);
}
For(i,1,sz){
pr[i]=++nd;
add(pr[i],pr[i-1]);
add(pr[i],vr[id][i-1].v1);
}
pos=0;
For(i,0,sz-1){
for (;pos!=sz&&vr[id][i].x>=vl[id][pos].x;++pos);
add(su[pos+1],pr[i+1]);
}
}
void solve(){
int mnx=1e9,mxx=1;
int mny=1e9,mxy=1;
For(i,1,n){
mnx=min(mnx,a[i].x2);
mxx=max(mxx,a[i].x1);
mny=min(mny,a[i].y2);
mxy=max(mxy,a[i].y1);
}
if (mnx>mxx) swap(mnx,mxx);
if (mny>mxy) swap(mny,mxy);
For(i,1,n){
a[i].x1=max(a[i].x1,mnx);
a[i].x2=min(a[i].x2,mxx);
a[i].y1=max(a[i].y1,mny);
a[i].y2=min(a[i].y2,mxy);
}
//cout<<mnx<<' '<<mny<<' '<<mxx<<' '<<mxy<<endl;
For(i,1,n){
int fl=0,s=0;
if (a[i].x1<=mnx&&mnx<=a[i].x2) fl|=1,++s;
if (a[i].x1<=mxx&&mxx<=a[i].x2) fl|=2,++s;
if (a[i].y1<=mny&&mny<=a[i].y2) fl|=4,++s;
if (a[i].y1<=mxy&&mxy<=a[i].y2) fl|=8,++s;
//cout<<fl<<' '<<s<<endl;
if (s>=3) continue;
if (s==0) return;
id[i][0]=++nd; id[i][1]=++nd;
if (s==1) add(id[i][1],id[i][0]);
For(j,0,3) if (fl&(1<<j)){
int flg=(s==1||(1<<j)<(fl^(1<<j))?0:1);
vl[j].PB((node){
j&2?a[i].x1:a[i].y1,id[i][flg],id[i][flg^1]});
vr[j].PB((node){
j&2?a[i].x2:a[i].y2,id[i][flg],id[i][flg^1]});
at[i][flg]=j;
}
}
For(i,0,3) build(i);
For(i,1,nd) if (!dfn[i]) tarjan(i);
For(i,1,n){
//cout<<id[i][0]<<' '<<id[i][1]<<endl;
//cout<<be[id[i][0]]<<' '<<be[id[i][1]]<<endl;
if (id[i][0]&&be[id[i][0]]==be[id[i][1]]) return;
}
static int mn[10],mx[10];
For(i,0,3){
mn[i]=(i&2?mnx:mny);
mx[i]=(i&2?mxx:mxy);
}
For(i,1,n) if (id[i][0]){
int flg=(be[id[i][0]]>be[id[i][1]]);
int idd=at[i][flg];
mn[idd]=max(mn[idd],(idd&2?a[i].x1:a[i].y1));
mx[idd]=max(mx[idd],(idd&2?a[i].x2:a[i].y2));
}
printf("%d %d\n",mnx,mn[0]);
printf("%d %d\n",mxx,mn[1]);
printf("%d %d\n",mn[2],mny);
printf("%d %d\n",mn[3],mxy);
exit(0);
}
}
void dfs2(int d){
int mnx=1e9;
For(i,1,n) if (!cnt[i]