半期考试(几近爆零场)
T3 大冒险
可以观察找规律!
最终把所有矩阵都给放在d*d的矩阵内,然后就变成了哪一个点没有被矩阵覆盖。
扫描线差不多的方法即可!
离线x维,然后y维用线段树区间修改。
#include<bits/stdc++.h> using namespace std; #define re register int #define py pair<int,int> const int N=2e5+6; struct node{int h, x, y, d;}A[N<<2]; inline bool cmp(const node&x, const node&y){return x.h<y.h;} int cnt, n, d; void add(int x, int y, int xx, int yy) { A[++cnt]=(node){x, y, yy, 1}; A[++cnt]=(node){xx+1, y, yy, -1}; } py tr[N<<2];int lzy[N<<2]; void build(int p,int l,int r) { tr[p]=py(0,l); lzy[p]=0; if(l==r)return; int mid=(l+r)>>1; build(p<<1,l,mid); build(p<<1|1,mid+1,r); tr[p]=min(tr[p<<1],tr[p<<1|1]); } inline void modi(int p,int d) { tr[p].first+=d; lzy[p]+=d; } inline void putdown(int p) { modi(p<<1,lzy[p]); modi(p<<1|1,lzy[p]); lzy[p]=0; } void ins(int p,int l,int r,int x,int y,int d) { if(x<=l&&r<=y){modi(p,d);return;} if(lzy[p])putdown(p); int mid=(l+r)>>1; if(x<=mid)ins(p<<1,l,mid,x,y,d); if(y>mid)ins(p<<1|1,mid+1,r,x,y,d); tr[p]=min(tr[p<<1],tr[p<<1|1]); } void work() { cnt=0; scanf("%d%d",&n,&d); int flag=0, x, y, xx, yy, f1, f2, t1, t2; while(n--) { scanf("%d%d%d%d",&x,&y,&xx,&yy); xx--;yy--; f1=x%d, f2=xx%d, t1=y%d, t2=yy%d; (f1+=d)%=d;(f2+=d)%=d;(t1+=d)%=d;(t2+=d)%=d; if(xx-x+1>=d&&yy-y+1>=d)flag=1; if(flag)continue; if(xx-x+1>=d) { if(t1<=t2) add(0, t1, d-1, t2); else add(0, 0, d-1, t2),add(0, t1, d-1, d-1); } else { if(f1<=f2) { if(yy-y+1>=d) add(f1, 0, f2, d-1); else { if(t1<=t2) add(f1, t1, f2, t2); else add(f1, 0, f2, t2),add(f1, t1, f2, d-1); } } else { if(yy-y+1>=d) { add(0, 0, f2, d-1); add(f1, 0, d-1, d-1); } else { if(t1<=t2) { add(0, t1, f2, t2); add(f1, t1, d-1, t2); } else { add(0, 0, f2, t2); add(0, t1, f2, d-1); add(f1, 0, d-1, t2); add(f1, t1, d-1, d-1); } } } } } if(flag){puts("NO");return;} sort(A+1,A+1+cnt,cmp); int nw=1; d--;build(1,0,d); for(re i=0;i<=d;++i) { while(nw<=cnt && A[nw].h<=i) { ins(1,0,d,A[nw].x,A[nw].y,A[nw].d); nw++; } py pos=tr[1]; if(pos.first==0) { puts("YES"); printf("%d %d\n", i, pos.second); return; } } puts("NO"); } signed main() { int T; scanf("%d",&T); while(T--)work(); return 0; }
T4 单调栈
如果没有-1,那么应该很容易想到笛卡尔树求答案,很简单。
但是有-1的话,他会导致笛卡尔树形态不一定,所以可以区间dp
#include<stdio.h> const int mo=1e9+7; int f[105][105][105], C[105][105], a[105]; signed main(){ C[0][0]=1; for(int i=1;i<=99;++i){ C[i][0]=1; for(int j=1;j<=99;++j) C[i][j]=(C[i-1][j]+C[i-1][j-1])%mo; }int T,n,l,r; scanf("%d",&T); while(T--){ scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&a[i]); for(int i=1;i<=n;++i)for(int j=i;j<=n;++j)for(int d=1;d<=n;++d) f[i][j][d]=0; for(int i=n;i;--i) for(int j=i;j<=n;++j) for(int k=i;k<=j;++k){ if(a[k]==-1)l=1,r=i; else l=r=a[k]; for(int d=l;d<=r;++d){ f[i][j][d]+=1LL*(i<k?f[i][k-1][d]:1)*(k<j?f[k+1][j][d+1]:1)%mo*C[j-i][k-i]%mo; if(f[i][j][d]>=mo)f[i][j][d]-=mo; } }printf("%d\n",f[1][n][1]); }return 0; }