【ContestHunter】【弱省胡策】【Round0】(A)&【Round1】(B)
DP+容斥原理or补集转化?/KD-Tree
唔……突然发现最早打的两场(打的最烂的两场)没有写记录……(太烂所以不忍记录了吗。。。
还是把搞出来了的两道题记录一下吧= =勉强算弥补一下缺憾……
Round0 A
要求问(1,2)->(n-1,m) & (2,1)->(n,m-1)的不相交路径条数,蒟蒻当时只想到了$N^3$的DP……即枚举当前的总步数,以及两个人分别横向走了几步。
其实正解是(也只能是?)$O(N^2)$的!
ans=calc{(1,2)->(n-1,m)}*calc{(2,1)->(n,m-1)} - calc{(1,2)->(n,m-1)}*calc{(2,1)->(n-1,m)}
后面减去的那是啥呢?是两个人走到对方的目的地的总方案数……也就是两人路径交叉的方案数!将交叉的后半段交换一下,与两人走到各自的目的地,且路径发生交叉的方案一一对应!
(还是容斥原理?)
我比较傻逼,边界情况没有处理全2333……比如(n-1,m)和(n,m-1)走不到啊什么的……
1 //Round0 A 2 #include<vector> 3 #include<cstdio> 4 #include<cstring> 5 #include<cstdlib> 6 #include<iostream> 7 #include<algorithm> 8 #define rep(i,n) for(int i=0;i<n;++i) 9 #define F(i,j,n) for(int i=j;i<=n;++i) 10 #define D(i,j,n) for(int i=j;i>=n;--i) 11 using namespace std; 12 typedef long long LL; 13 inline int getint(){ 14 int r=1,v=0; char ch=getchar(); 15 for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1; 16 for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch; 17 return r*v; 18 } 19 const int N=2010,mod=1e9+7; 20 /*******************template********************/ 21 int n,m,a[N][N]; 22 int f[N][N]; 23 char s[N]; 24 25 LL calc(int x1,int y1,int x2,int y2){ 26 memset(f,0,sizeof f); 27 f[x1][y1]=1; 28 F(i,x1,x2) F(j,y1,y2){ 29 if (a[i-1][j]) (f[i][j]+=f[i-1][j])%=mod; 30 if (a[i][j-1]) (f[i][j]+=f[i][j-1])%=mod; 31 } 32 return f[x2][y2]; 33 } 34 int main(){ 35 #ifndef ONLINE_JUDGE 36 freopen("A.in","r",stdin); 37 freopen("A.out","w",stdout); 38 #endif 39 n=getint(); m=getint(); 40 41 F(i,1,n){ 42 scanf("%s",s+1); 43 F(j,1,m) a[i][j]=s[j]=='0'; 44 } 45 // printf("%lld %lld %lld %lld\n",calc(1,2,n-1,m),calc(2,1,n,m-1),calc(1,2,n,m-1),calc(2,1,n-1,m)); 46 if (a[1][2] && a[2][1] && a[n-1][m] && a[n][m-1]) 47 printf("%lld\n",(calc(1,2,n-1,m)*calc(2,1,n,m-1)%mod-calc(1,2,n,m-1)*calc(2,1,n-1,m)%mod+mod)%mod); 48 else puts("0"); 49 return 0; 50 }
Round1 B
题意是求四维空间中的偏序最长链?。。。
点数不多,排序以后暴力枚举每个点,求出在它之前出现的满足条件的点中,最大的DP值。
记得做这场胡策的时候我刚学了KD-Tree = =
然而我爆零了……
为什么呢?不是估价了嘛……我把小于号写成大于号了……也就是说,我把可能成为ans的全部避!过!去!了!
标算是搞完一个点以后进行修改,然而蒟蒻没有yy出来怎么修改……窝的做法是每算完一个点就把它插进去,然后重构啊之类的搞搞……(真是机(sha)智(bi)
1 //Round 1 B 2 #include<vector> 3 #include<cstdio> 4 #include<cstring> 5 #include<cstdlib> 6 #include<iostream> 7 #include<algorithm> 8 #define rep(i,n) for(int i=0;i<n;++i) 9 #define F(i,j,n) for(int i=j;i<=n;++i) 10 #define D(i,j,n) for(int i=j;i>=n;--i) 11 using namespace std; 12 typedef long long LL; 13 inline int getint(){ 14 int r=1,v=0; char ch=getchar(); 15 for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1; 16 for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch; 17 return r*v; 18 } 19 const int N=1e5+10,INF=1e9; 20 /*******************template********************/ 21 22 int n,m,p[N],D,root; 23 struct node{ 24 int d[4],mx[4],mn[4],l,r,D,size,v,maxv; 25 int& operator [] (int x){return d[x];} 26 void read(){F(i,0,3) d[i]=getint();} 27 }t[N],t2[N],tmp; 28 29 bool cmp(int x,int y){return t[x][D]<t[y][D];} 30 bool operator < (node a,node b){ 31 F(i,0,3){ 32 if (a[i]<b[i]) return 1; 33 if (a[i]>b[i]) return 0; 34 } 35 return 0; 36 } 37 #define L t[o].l 38 #define R t[o].r 39 #define mid (l+r>>1) 40 41 void Push_up(int o){ 42 F(i,0,3){ 43 t[o].mn[i]=min(t[o][i],min(t[L].mn[i],t[R].mn[i])); 44 t[o].mx[i]=max(t[o][i],max(t[L].mx[i],t[R].mx[i])); 45 } 46 t[o].maxv=max(t[o].v,max(t[L].maxv,t[R].maxv)); 47 t[o].size=t[L].size+t[R].size+1; 48 } 49 int build(int l,int r,int dir){ 50 D=dir; 51 nth_element(p+l,p+mid,p+r+1,cmp); 52 int o=p[mid]; 53 t[o].D=dir; 54 L = l < mid ? build(l,mid-1,(dir+1)%4) : 0; 55 R = r > mid ? build(mid+1,r,(dir+1)%4) : 0; 56 Push_up(o); 57 return o; 58 } 59 60 int cnt; 61 void dfs(int o){ 62 if (!o) return; 63 p[++cnt]=o; 64 dfs(L); dfs(R); 65 } 66 void rebuild(int &o){ 67 cnt=0; 68 dfs(o); 69 o=build(1,cnt,t[o].D); 70 } 71 72 void Insert(int &o,int dir){ 73 if (!o){ 74 o=++m; t[o].D=dir; 75 t[o]=tmp; 76 F(i,0,3) t[o].mn[i]=t[o].mx[i]=t[o][i]; 77 t[o].maxv=t[o].v; t[o].size=1; 78 return; 79 } 80 if (t[o][dir]<tmp[dir]){ 81 Insert(L,(dir+1)%4); 82 Push_up(o); 83 if (t[L].size>t[o].size*0.7) rebuild(o); 84 }else{ 85 Insert(R,(dir+1)%4); 86 Push_up(o); 87 if (t[R].size>t[o].size*0.7) rebuild(o); 88 } 89 } 90 91 int check(int o){ 92 if (!o) return 0; 93 int ans=0; 94 F(i,0,3) if(t[o].mx[i]<=tmp[i]) ans++; 95 if (ans==4) return ans; 96 ans=1; 97 F(i,0,3) if (t[o].mn[i]>tmp[i]) ans=0; 98 return ans; 99 } 100 int dis(node a,node b){ 101 F(i,0,3) if (a[i]>b[i]) return 0; 102 return a.v; 103 } 104 int ans; 105 void query(int o){ 106 ans=max(dis(t[o],tmp),ans); 107 int dl=check(L),dr=check(R); 108 if (dl==4) ans=max(ans,t[L].maxv); 109 else if (dl && ans<t[L].maxv) query(L); 110 if (dr==4) ans=max(ans,t[R].maxv); 111 else if (dr && ans<t[R].maxv) query(R); 112 } 113 114 int main(){ 115 #ifndef ONLINE_JUDGE 116 freopen("B.in","r",stdin); 117 freopen("B.out","w",stdout); 118 #endif 119 F(i,0,3) t[0].mn[i]=INF,t[0].mx[i]=-INF; 120 t[0].maxv=-INF; 121 122 n=getint(); 123 F(i,1,n) t2[i].read(),t2[i].v=1; 124 sort(t2+1,t2+n+1); 125 /* t[m=1]=t2[1]; t[1].v=1; 126 F(i,2,n){ 127 F(j,0,3) if (t2[i][j]!=t2[i-1][j]){ t[++m]=t2[i]; break;} 128 t[m].v++; 129 } 130 F(i,1,m) t2[i]=t[i]; 131 n=m; m=0; 132 */ int anss=0; 133 F(i,1,n){ 134 ans=0; 135 tmp=t2[i]; 136 query(root); 137 t2[i].v+=ans; 138 // printf("%d ",t2[i].v); 139 tmp=t2[i]; 140 anss=max(anss,t2[i].v); 141 Insert(root,0); 142 } 143 // puts(""); 144 printf("%d\n",anss); 145 return 0; 146 }