T1:
最优解显然是选择一个区间。我们枚举右端点,显然左端点单调不减。
写个分治就能AC啦(话说为什么我分析出单调性后连分治都想不到)。
考场44分代码:
1 #pragma GCC optimize("Ofast") 2 #include<cstdio> 3 #include<algorithm> 4 #include<cctype> 5 typedef long long int lli; 6 using namespace std; 7 const int maxe=1e6+1e2,maxn=1e5,maxl=20; 8 // I am a sb and I can't solve any problem, although all over the world has solved T1. 9 // Compilation technology is well developed, we don't need to support it. 10 11 int n,m; 12 13 struct RMQ { 14 struct Array { 15 int dat[maxe][maxl]; 16 inline int* operator () (const int &i,const int &j) { // i is kind , j is pos . 17 return dat[n*(i-1)+j]; 18 } 19 }arr; 20 int Log[maxn]; 21 22 inline void init() { 23 for(int i=2;i<=n;i++) Log[i] = Log[i>>1] + 1; 24 for(int i=1;i<=m;i++) for(int k=1;k<=Log[n];k++) for(int j=1;j<=n;j++) 25 arr(i,j)[k] = max( arr(i,j)[k-1] , arr(i,j+(1<<(k-1)))[k-1] ); 26 } 27 inline int query(int k,int l,int r) { 28 const int Lo = Log[r-l+1]; 29 return max( arr(k,l)[Lo] , arr(k,r-(1<<Lo)+1)[Lo] ); 30 } 31 }RMQ; 32 33 lli su[maxn],f[maxn],ans; 34 35 inline char nextchar() { 36 static const int BS = 1 << 21; 37 static char buf[BS],*st,*ed; 38 if( st == ed ) ed = buf + fread(st=buf,1,BS,stdin); 39 return st == ed ? -1 : *st++; 40 } 41 inline int getint() { 42 int ret = 0 , ch; 43 while( !isdigit(ch=nextchar()) ) ; 44 do ret = ret * 10 + ch - '0'; while( isdigit(ch=nextchar()) ); 45 return ret; 46 } 47 int main() { 48 n = getint() , m = getint(); 49 for(int i=2;i<=n;i++) su[i] = su[i-1] + getint(); 50 for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) *RMQ.arr(j,i) = getint(); 51 RMQ.init(); 52 for(int r=n,l=n;r;r--) { 53 l = min( l , r ); 54 for(int j=l;j;j--) { 55 f[j] = su[j] - su[r]; 56 for(int k=1;k<=m;k++) f[j] += RMQ.query(k,j,r); 57 if( f[j] >= f[l] ) l = j; 58 } 59 ans = max( ans , f[l] ); 60 } 61 printf("%lld ",ans); 62 return 0; 63 }
正解代码:
1 #pragma GCC optimize("Ofast") 2 #include<cstdio> 3 #include<algorithm> 4 #include<cctype> 5 typedef long long int lli; 6 using namespace std; 7 const int maxe=1e6+1e5+1e2,maxn=1e5+1e2,maxl=20; 8 const lli inf=0x3f3f3f3f3f3f3f3fll; 9 10 int n,m; 11 12 struct RMQ { 13 struct Array { 14 int dat[maxe][maxl]; 15 inline int* operator () (const int &i,const int &j) { // i is kind , j is pos . 16 return dat[n*(i-1)+j]; 17 } 18 }arr; 19 int Log[maxn]; 20 21 inline void init() { 22 for(int i=2;i<=n;i++) Log[i] = Log[i>>1] + 1; 23 for(int i=1;i<=m;i++) for(int k=1;k<=Log[n];k++) for(int j=1;j<=n;j++) 24 arr(i,j)[k] = max( arr(i,j)[k-1] , arr(i,j+(1<<(k-1)))[k-1] ); 25 } 26 inline int query(int k,int l,int r) { 27 const int Lo = Log[r-l+1]; 28 return max( arr(k,l)[Lo] , arr(k,r-(1<<Lo)+1)[Lo] ); 29 } 30 }RMQ; 31 32 lli su[maxn],f[maxn],ans; 33 34 inline lli calc(int ll,int rr) { 35 if( ll > rr ) return -inf; 36 lli ret = su[ll] - su[rr]; 37 for(int i=1;i<=m;i++) ret += RMQ.query(i,ll,rr); 38 return ret; 39 } 40 inline void solve(int l_l,int l_r,int r_l,int r_r) { 41 if( r_l == r_r ) { 42 for(int i=l_l;i<=l_r;i++) ans = max( ans , calc(i,r_l) ); 43 return; 44 } const int r_mid = ( r_l + r_r ) >> 1; 45 int l_mid = l_l; f[l_l] = calc(l_l,r_mid); 46 for(int i=l_l;i<=l_r;i++) if( ( f[i] = calc(i,r_mid) ) > f[l_mid] ) l_mid = i; 47 ans = max( ans , f[l_mid] ); 48 solve(l_l,l_mid,r_l,r_mid) , solve(l_mid,l_r,r_mid+1,r_r); 49 } 50 51 inline char nextchar() { 52 static const int BS = 1 << 21; 53 static char buf[BS],*st,*ed; 54 if( st == ed ) ed = buf + fread(st=buf,1,BS,stdin); 55 return st == ed ? -1 : *st++; 56 } 57 inline int getint() { 58 int ret = 0 , ch; 59 while( !isdigit(ch=nextchar()) ) ; 60 do ret = ret * 10 + ch - '0'; while( isdigit(ch=nextchar()) ); 61 return ret; 62 } 63 64 int main() { 65 n = getint() , m = getint(); 66 for(int i=2;i<=n;i++) su[i] = su[i-1] + getint(); 67 for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) *RMQ.arr(j,i) = getint(); 68 RMQ.init() , solve(1,n,1,n); 69 printf("%lld ",ans); 70 return 0; 71 }
T2:
暴力高斯消元大家都会。
考虑我们把图按照与原点的曼哈顿距离分层,显然i层的变量只跟i-1层和i+1层有关。
我们能从外层向内层带入,用i,i+1,i+2三层的方程,高斯消元,用第i层表示第i+1层的方程。
然后在继续迭代(i-1,i,i+1)层。后来写这个代码的时候我已经十分混乱了......
考场45分代码:
1 #pragma GCC optimize("Ofast") 2 #include<cstdio> 3 #include<algorithm> 4 typedef long long int lli; 5 const int maxn=31,maxe=3e3+1e1; 6 const int mod=1e9+7; 7 8 inline int sub(const int &x,const int &y) { 9 const int ret = x - y; 10 return ret < 0 ? ret + mod : ret; 11 } 12 inline int mul(const int &x,const int &y) { 13 return (lli) x * y % mod; 14 } 15 inline void adde(int &dst,const int &x) { 16 if( ( dst += x ) >= mod ) dst -= mod; 17 } 18 inline void sube(int &dst,const int &x) { 19 if( ( dst -= x ) < 0 ) dst += mod; 20 } 21 inline void mule(int &dst,const int &x) { 22 dst = (lli) dst * x % mod; 23 } 24 inline int fastpow(int base,int tim) { 25 int ret = 1; 26 while(tim) { 27 if( tim & 1 ) mule(ret,base); 28 if( tim >>= 1 ) mule(base,base); 29 } 30 return ret; 31 } 32 33 int dat[maxe][maxe]; 34 int n,r; 35 36 struct Array { 37 int dat[maxe]; 38 inline int& operator () (int x,int y) { 39 x += r , y += r; 40 return dat[x*(r*2+1)+y]; 41 } 42 }id; 43 44 inline int gid(int x,int y) { 45 if( x < -r || x > r || y < -r || y > r ) return n; 46 return id(x,y); 47 } 48 49 50 inline bool inside(int x,int y) { 51 return x * x + y * y <= r * r; 52 } 53 54 inline void gauss() { 55 for(int i=1,pos;i<=n;i++) { 56 pos = -1; 57 for(int j=i;j<=n;j++) if( dat[j][i] ) { pos = j; break; } 58 if( !~pos ) continue; 59 if( pos != i ) { 60 for(int k=1;k<=n+1;k++) std::swap(dat[pos][k],dat[i][k]); 61 pos = i; 62 } 63 const int inv = fastpow(dat[i][i],mod-2); 64 for(int k=1;k<=n+1;k++) mule(dat[i][k],inv); 65 for(int j=1;j<=n;j++) if( i != j && dat[j][i] ) { 66 const int m = dat[j][i]; 67 for(int k=1;k<=n+1;k++) sube(dat[j][k],mul(m,dat[i][k])); 68 } 69 } 70 } 71 72 const int dx[]={1,0,-1,0},dy[]={0,1,0,-1}; 73 int in[4],su; 74 75 inline void build() { 76 for(int i=-r;i<=r;i++) for(int j=-r;j<=r;j++) if( inside(i,j) ) id(i,j) = ++n; 77 ++n; for(int i=-r;i<=r;i++) for(int j=-r;j<=r;j++) if( !inside(i,j) ) id(i,j) = n; 78 for(int i=-r;i<=r;i++) for(int j=-r;j<=r;j++) if( inside(i,j) ) { 79 for(int k=0;k<4;k++) { 80 const int sx = i + dx[k] , sy = j + dy[k]; 81 adde(dat[id(i,j)][gid(sx,sy)],sub(0,in[k])); 82 } 83 dat[id(i,j)][id(i,j)] = 1 , dat[id(i,j)][n+1] = 1; 84 } 85 dat[n][n] = 1; 86 } 87 88 int main() { 89 scanf("%d",&r); 90 for(int i=0;i<4;i++) scanf("%d",in+i) , adde(su,in[i]); 91 const int inv = fastpow(su,mod-2); 92 for(int i=0;i<4;i++) mule(in[i],inv); 93 build() , gauss() , printf("%d ",dat[id(0,0)][n+1]); 94 return 0; 95 }
正解代码:
1 #pragma GCC optimize("Ofast") 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<algorithm> 6 #include<vector> 7 #include<cstdlib> 8 #define debug cout 9 using namespace std; 10 typedef long long int lli; 11 const int maxn=1e2+1e1; 12 const int mod=1e9+7; 13 const int dx[]={1,0,-1,0},dy[]={0,1,0,-1}; 14 15 inline int sub(const int &x,const int &y) { 16 const int ret = x - y; 17 return ret < 0 ? ret + mod : ret; 18 } 19 inline int mul(const int &x,const int &y) { 20 return (lli) x * y % mod; 21 } 22 inline void adde(int &dst,const int &x) { 23 if( ( dst += x ) >= mod ) dst -= mod; 24 } 25 inline void sube(int &dst,const int &x) { 26 if( ( dst -= x ) < 0 ) dst += mod; 27 } 28 inline void mule(int &dst,const int &x) { 29 dst = (lli) dst * x % mod; 30 } 31 inline int fastpow(int base,int tim) { 32 int ret = 1; 33 while(tim) { 34 if( tim & 1 ) mule(ret,base); 35 if( tim >>= 1 ) mule(base,base); 36 } 37 return ret; 38 } 39 40 int dat[maxn<<3][maxn<<3]; 41 bool isOutside[maxn<<3]; 42 int at[maxn<<3]; 43 44 inline void gauss(int n,int es) { // n is number of xs , es is number of equations . 45 for(int i=1,pos,used=0;i<=n;i++) if( isOutside[i] ) { 46 pos = -1; 47 for(int j=++used;j<=es;j++) if( dat[j][i] ) { pos = j; break; } 48 if( !~pos ) continue; 49 if( pos != used ) { 50 for(int k=0;k<=n;k++) std::swap(dat[pos][k],dat[used][k]); 51 pos = used; 52 } at[i] = used; 53 const int inv = fastpow(dat[used][i],mod-2); 54 for(int k=0;k<=n;k++) mule(dat[used][k],inv); 55 for(int j=1;j<=es;j++) if( used != j && dat[j][i] ) { 56 const int m = dat[j][i]; 57 for(int k=0;k<=n;k++) sube(dat[j][k],mul(m,dat[used][k])); 58 } 59 } 60 } 61 62 struct NamePool { 63 int stk[maxn<<3],top; 64 inline void deleteName(int x) { stk[++top] = x; } 65 inline int newName() { return stk[top--]; } 66 NamePool() { for(int i=(maxn<<2)-1;i;i--) deleteName(i); } 67 inline int usedSize() { return (maxn<<2) - 1 - top; } 68 }np; 69 70 int id[maxn][maxn]; 71 int tmp[maxn][maxn][maxn<<3]; // temp equations . 72 int in[4],su,r; 73 const int FS = 800; 74 75 struct Point { int x,y; }; 76 vector<Point> ps[maxn<<2]; 77 78 inline void newLevel(const vector<Point> &ps) { 79 for(unsigned i=0;i<ps.size();i++) id[ps[i].x][ps[i].y] = np.newName(); 80 } 81 inline void removeLevel(const vector<Point> &ps) { 82 for(unsigned i=ps.size()-1;~i;i--) np.deleteName(id[ps[i].x][ps[i].y]); 83 } 84 inline int dis(int x,int y) { 85 return abs(r-x) + abs(r-y); 86 } 87 inline void buildLevel(const vector<Point> &ps) { // build this level , and copy tmp equations . 88 memset(dat,0,sizeof(dat)); 89 int cnt = 0; 90 for(unsigned i=0;i<ps.size();i++) { 91 const int cc = id[ps[i].x][ps[i].y]; ++cnt; 92 for(int j=0;j<4;j++) { 93 const int tx = ps[i].x + dx[j] , ty = ps[i].y + dy[j]; 94 if( tx < 0 || ty < 0 ) continue; 95 if( dis(tx,ty) > dis(ps[i].x,ps[i].y) ) { 96 const int m = in[j]; 97 adde(dat[cnt][0],mul(m,tmp[tx][ty][0])); 98 for(int j=1;j<=FS;j++) sube(dat[cnt][j],mul(m,tmp[tx][ty][j])); 99 } else adde(dat[cnt][id[tx][ty]],sub(0,in[j])); 100 } 101 adde(dat[cnt][cc],1) , adde(dat[cnt][0],1); 102 } 103 } 104 inline void markLevel(const vector<Point> &ps,const bool &v) { 105 for(unsigned i=0;i<ps.size();i++) isOutside[id[ps[i].x][ps[i].y]] = v; 106 } 107 inline void storeLevel(const vector<Point> ps,int n) { 108 for(unsigned i=0;i<ps.size();i++) { 109 const int pos = at[id[ps[i].x][ps[i].y]]; 110 tmp[ps[i].x][ps[i].y][0] = dat[pos][0]; 111 for(int j=1;j<=n;j++) if( j != id[ps[i].x][ps[i].y] ) 112 tmp[ps[i].x][ps[i].y][j] = sub(0,dat[pos][j]); 113 } 114 } 115 inline void trans(int lev) { // level is new outside level . 116 newLevel(ps[lev-1]) , buildLevel(ps[lev]) , markLevel(ps[lev],1); 117 gauss(FS,ps[lev].size()) , storeLevel(ps[lev],FS); 118 markLevel(ps[lev],0) , removeLevel(ps[lev]); 119 } 120 inline int calcCent() { 121 int sul = 1 , sur = 1; 122 for(int i=0;i<4;i++) { 123 const int tx = r + dx[i] , ty = r + dy[i]; 124 sube(sul,mul(tmp[tx][ty][id[r][r]],in[i])) , adde(sur,mul(tmp[tx][ty][0],in[i])); 125 } 126 return mul(sur,fastpow(sul,mod-2)); 127 } 128 129 inline bool inside(int x,int y) { 130 return (r-x)*(r-x) + (r-y)*(r-y) <= r * r; 131 } 132 133 int main() { 134 scanf("%d",&r); 135 for(int i=0;i<4;i++) scanf("%d",in+i) , adde(su,in[i]); 136 const int inv = fastpow(su,mod-2); 137 for(int i=0;i<4;i++) mule(in[i],inv); 138 for(int i=0;i<=r<<1;i++) 139 for(int j=0;j<=r<<1;j++) 140 if( inside(i,j) ) ps[dis(i,j)].push_back((Point){i,j}); 141 for(int i=r<<1,fir=1;i;i--) if( ps[i].size() ) { 142 if(fir) newLevel(ps[i]) , fir = 0; 143 trans(i); 144 } 145 printf("%d ",calcCent()); 146 return 0; 147 }
T3:
找规矩神仙题,我只会dfs,还是WA的。
题解:
考场30分代码:
1 #include<cstdio> 2 #include<utility> 3 #include<queue> 4 #include<cctype> 5 #define bool unsigned char 6 typedef std::pair<int,int> pii; 7 using namespace std; 8 const int maxn=5e2+1e1; 9 10 bool in[maxn][maxn]; 11 int n,m,ans; 12 queue<pii> q; 13 14 inline void update(int x,int y) { 15 for(int i=1;i<=n;i++) if( in[y][i] && !in[i][x] ) in[i][x] = 1 , q.push(make_pair(i,x)); 16 } 17 18 inline char nextchar() { 19 static const int BS = 1 << 20; 20 static char buf[BS],*st,*ed; 21 if( st == ed ) ed = buf + fread(st=buf,1,BS,stdin); 22 return st == ed ? -1 : *st++; 23 } 24 inline int getint() { 25 int ret = 0 , ch; 26 while( !isdigit(ch=nextchar()) ) ; 27 do ret = ret * 10 + ch - '0'; while( isdigit(ch=nextchar()) ); 28 return ret; 29 } 30 31 int main() { 32 n = getint() , m = getint(); 33 for(int i=1,a,b;i<=m;i++) a = getint() , b = getint() , in[a][b] = 1 , q.push(make_pair(a,b)); 34 while( q.size() ) update(q.front().first,q.front().second) , q.pop(); 35 for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) ans += in[i][j]; 36 printf("%d ",ans); 37 return 0; 38 }
正解代码:
1 #include<cstdio> 2 #include<cstring> 3 typedef long long int lli; 4 const int maxn=1e5+1e2; 5 6 int s[maxn],t[maxn<<1],nxt[maxn<<1],mrk[maxn]; 7 bool vis[maxn],fail; 8 int cnt[3],ecnt; 9 10 inline void addedge(int from,int to) { 11 static int cnt; 12 t[++cnt] = to , nxt[cnt] = s[from] , s[from] = cnt; 13 } 14 inline void dfs(int pos,int col) { 15 static const int ne[]={1,2,0},pr[]={2,0,1}; 16 if( vis[pos] ) return void(fail |= col != mrk[pos]); 17 vis[pos] = 1 , ++cnt[mrk[pos]=col]; 18 for(int at=s[pos];at;at=nxt[at]) ++ecnt , dfs(t[at],(at&1)?ne[col]:pr[col]); 19 } 20 21 int main() { 22 static int n,m; 23 static lli ans; 24 scanf("%d%d",&n,&m); 25 for(int i=1,a,b;i<=m;i++) scanf("%d%d",&a,&b) , addedge(a,b) , addedge(b,a); 26 for(int i=1;i<=n;i++) if( !vis[i] ) { 27 memset(cnt,0,sizeof(cnt)) , ecnt = fail = 0 , dfs(i,0); 28 if(fail) ans += (lli) ( cnt[0] + cnt[1] + cnt[2] ) * ( cnt[0] + cnt[1] + cnt[2] ); 29 else if( !cnt[0] || !cnt[1] || !cnt[2] ) ans += ecnt >> 1; 30 else ans += (lli) cnt[0] * cnt[1] + (lli) cnt[1] * cnt[2] + (lli) cnt[2] * cnt[0]; 31 } 32 printf("%lld ",ans); 33 return 0; 34 }
为什么活着本身,要顾忌那么多的事情?
感觉活下去,好累......