C Gargari and Bishops
题意:一个n*n的矩阵,每个元素一个值, aij,要求选两个点,在上面放置骑士(暂且这样理解), 骑士能够攻击与它在同一对角线上面的格子,不能存在一个格子同时被两个骑士攻击,且使得所有被攻击的格子的值加起来最大.
分析:
与某一点(i, j)在同一对角线的格子的坐标(x, y)满足,i+j = x+y, 或者abs(i-j) = abs(i-j), 所以先求出所有对角线上格子值总和,因为两个骑士所在对角线不能重合,画图很容易知道,要满足两个骑士的坐标i,j之和一个奇数一个偶数。
所以最后把(i+j)为奇数和偶数的点所在对角线格子值之和加起来就行了。
代码:
1 //Template updates date: 20140718 2 #include <bits/stdc++.h> 3 #define esp 1e-6 4 #define inf 0x3f3f3f3f 5 #define pi acos(-1.0) 6 #define pb push_back 7 #define lson l, m, rt<<1 8 #define rson m+1, r, rt<<1|1 9 #define lowbit(x) (x&(-x)) 10 #define mp(a, b) make_pair((a), (b)) 11 #define bit(k) (1<<(k)) 12 #define iin freopen("pow.in", "r", stdin); 13 #define oout freopen("pow.out", "w", stdout); 14 #define in freopen("solve_in.txt", "r", stdin); 15 #define out freopen("solve_out.txt", "w", stdout); 16 #define bug puts("********))))))"); 17 #define Inout iin oout 18 #define inout in out 19 20 #define SET(a, v) memset(a, (v), sizeof(a)) 21 #define SORT(a) sort((a).begin(), (a).end()) 22 #define REV(a) reverse((a).begin(), (a).end()) 23 #define READ(a, n) {REP(i, n) cin>>(a)[i];} 24 #define REP(i, n) for(int i = 0; i < (n); i++) 25 #define VREP(i, n, base) for(int i = (n); i >= (base); i--) 26 #define Rep(i, base, n) for(int i = (base); i < (n); i++) 27 #define REPS(s, i) for(int i = 0; (s)[i]; i++) 28 #define pf(x) ((x)*(x)) 29 #define mod(n) ((n)) 30 #define Log(a, b) (log((double)b)/log((double)a)) 31 #define Srand() srand((int)time(0)) 32 #define random(number) (rand()%number) 33 #define random_range(a, b) (int)(((double)rand()/RAND_MAX)*(b-a) + a) 34 35 using namespace std; 36 typedef long long LL; 37 typedef unsigned long long ULL; 38 typedef vector<int> VI; 39 typedef pair<int,int> PII; 40 typedef vector<PII> VII; 41 typedef vector<PII, int> VIII; 42 typedef VI:: iterator IT; 43 typedef map<string, int> Mps; 44 typedef map<int, int> Mpi; 45 typedef map<int, PII> Mpii; 46 typedef map<PII, int> Mpiii; 47 using namespace std; 48 49 const int maxn = 2222; 50 51 LL a[maxn][maxn],sum[2*maxn][2]; 52 PII ans[2]; 53 LL v[2]; 54 55 int main(){ 56 57 int n; 58 scanf("%d", &n); 59 v[0] = v[1] = -1; 60 for(int i = 1; i <= n; i++) 61 for(int j = 1; j <= n; j++){ 62 scanf("%I64d", &a[i][j]); 63 sum[i+j][0] += a[i][j]; 64 sum[i-j+n][1] += a[i][j]; 65 } 66 67 for(int i = 1; i <= n; i++) 68 for(int j = 1; j <= n; j++){ 69 int parity = (i+j)&1; 70 LL tmp = sum[i+j][0]+sum[i-j+n][1]-a[i][j]; 71 if(parity){ 72 if(tmp > v[1]) 73 v[1] = tmp, ans[1] = mp(i, j); 74 } 75 else if(tmp > v[0]) 76 v[0] = tmp, ans[0] = mp(i, j); 77 } 78 cout << v[0]+v[1] << endl; 79 cout << ans[0].first << ' ' << ans[0].second << ' ' << ans[1].first << ' ' << ans[1].second << endl; 80 return 0; 81 }
D Gargari and Permutations
题意:k个 1~n的排列,求出这k个排列的最长公共字串(LCS)。
分析:大白书上面做过一道题,不过,只是两个1~n的排列的LCS,其实这题就是扩展一下。最后提交时ans 取的是dp[n],正解应该是max{dp[i]}啊!就是这样被自己坑的。继续分析:求2个排列的LCS时,求出第2个排列中各个数在第一个排列中的位置,得到一个新的序列,求这个序列的最长上升子序列就行了。
对于k个的情况,首先对第2~k个排列,求出其中每个元素在第一个排列中的位置,得到新的序列用来更新之前的序列,然后对于第3~k个排列求出在第2个排列中的位置,这样一直仅剩一个排列,然后对这个排列求LIS,注意这里的上升子序列除了满足当前序列满足上升,当前序列中元素表示的相应位置的上一个序列中元素也应该满足上升!一直这样判断知道倒数第二个序列!
代码:
1 //Template updates date: 20140718 2 #include <bits/stdc++.h> 3 #define esp 1e-6 4 #define inf 0x3f3f3f3f 5 #define pi acos(-1.0) 6 #define pb push_back 7 #define lson l, m, rt<<1 8 #define rson m+1, r, rt<<1|1 9 #define lowbit(x) (x&(-x)) 10 #define mp(a, b) make_pair((a), (b)) 11 #define bit(k) (1<<(k)) 12 #define iin freopen("pow.in", "r", stdin); 13 #define oout freopen("pow.out", "w", stdout); 14 #define in freopen("solve_in.txt", "r", stdin); 15 #define out freopen("solve_out.txt", "w", stdout); 16 #define bug puts("********))))))"); 17 #define Inout iin oout 18 #define inout in out 19 20 #define SET(a, v) memset(a, (v), sizeof(a)) 21 #define SORT(a) sort((a).begin(), (a).end()) 22 #define REV(a) reverse((a).begin(), (a).end()) 23 #define READ(a, n) {REP(i, n) cin>>(a)[i];} 24 #define REP(i, n) for(int i = 0; i < (n); i++) 25 #define VREP(i, n, base) for(int i = (n); i >= (base); i--) 26 #define Rep(i, base, n) for(int i = (base); i < (n); i++) 27 #define REPS(s, i) for(int i = 0; (s)[i]; i++) 28 #define pf(x) ((x)*(x)) 29 #define mod(n) ((n)) 30 #define Log(a, b) (log((double)b)/log((double)a)) 31 #define Srand() srand((int)time(0)) 32 #define random(number) (rand()%number) 33 #define random_range(a, b) (int)(((double)rand()/RAND_MAX)*(b-a) + a) 34 35 using namespace std; 36 typedef long long LL; 37 typedef unsigned long long ULL; 38 typedef vector<int> VI; 39 typedef pair<int,int> PII; 40 typedef vector<PII> VII; 41 typedef vector<PII, int> VIII; 42 typedef VI:: iterator IT; 43 typedef map<string, int> Mps; 44 typedef map<int, int> Mpi; 45 typedef map<int, PII> Mpii; 46 typedef map<PII, int> Mpiii; 47 using namespace std; 48 49 const int maxn = 1111; 50 int a[maxn][10], b[maxn]; 51 52 int dp[maxn], pos[maxn]; 53 int n, m; 54 bool check(int x, int y) 55 { 56 for(int k = m; k > 1; k--) 57 { 58 if(a[x][k] > a[y][k]) 59 { 60 x = a[x][k]; 61 y = a[y][k]; 62 } 63 else return false; 64 } 65 return true; 66 } 67 68 int main() 69 { 70 71 scanf("%d%d", &n, &m); 72 for(int k = 1; k <= m; k++) 73 for(int i = 1; i <= n; i++) 74 { 75 scanf("%d", &a[i][k]); 76 } 77 for(int i = 1; i <= m; i++) 78 { 79 for(int j = 1; j <= n; j++){ 80 pos[a[j][i]] = j;} 81 for(int k = i+1; k <= m; k++) 82 for(int j = 1; j <= n; j++) 83 a[j][k] = pos[a[j][k]]; 84 } 85 for(int i = 1; i <= n; i++) 86 for(int j = 0; j < i; j++) 87 { 88 if(check(i, j) || j == 0) 89 dp[i] = max(dp[i], dp[j]+1); 90 } 91 int ans = 0; 92 for(int i = 1; i <= n; i++){ 93 ans = max(dp[i], ans); 94 } 95 cout<<ans<<endl; 96 return 0; 97 }
E Caisa and Tree
题意:一棵n个结点的树,1为根,每个结点一直正值,两种操作,1 v 求出根节点到v结点的路径上经过的点值中与val[v]不互质的点编号,且尽量靠近v,
2 w v 将编号为w 的点值修改为v。操作2个数不会超过50.
分析:
由于修改操作不会很多,因此每次修改后都暴力dfs更新相应结点的答案。将1-v路径上经过的结点val值所含的质因数都加入到相应数组,然后对于v的每个质因子找到
之前包含它的结点,最后去深度最大的。
代码:
1 #include <bits/stdc++.h> 2 #define in freopen("solve_in.txt", "r", stdin); 3 #define esp 1e-10 4 #define bug(x) printf("Line %d:>>>>> ", (x)); 5 #define inf 0x0f0f0f0f 6 #define pb push_back 7 using namespace std; 8 typedef vector<int> :: reverse_iterator RIT; 9 10 typedef unsigned long long ULL; 11 typedef long long LL; 12 const int maxm = 2*(int)1e6+100; 13 const int maxn = (int)1e5+10; 14 vector<int> h[maxm], g[maxn]; 15 int val[maxn], l[maxn], r[maxn], ans[maxn], dep[maxn]; 16 vector<int> prime; 17 int vis[2000]; 18 int n, q, cnt; 19 20 void pre() { 21 for(int i = 2; i <= 1555; i++) { 22 if(vis[i] == 0) { 23 prime.pb(i); 24 for(int j = i*i; j <= 1555; j+= i) 25 vis[j] = 1; 26 } 27 } 28 } 29 int findx(int val) { 30 if(h[val].size()) 31 return h[val][h[val].size()-1]; 32 return 0; 33 } 34 void insertVal(int x, int v) { 35 h[x].pb(v); 36 } 37 void deleteVal(int x) { 38 if(h[x].size()) 39 h[x].pop_back(); 40 } 41 void dfs(int u, int pos, bool all, int nod, int fa) { 42 ans[u] = 0; 43 int tmp = val[u]; 44 for(int i = 0; i < prime.size() && prime[i]*prime[i] <= tmp; i++) { 45 if(tmp % prime[i] == 0) { 46 int v = findx(prime[i]); 47 if(dep[ans[u]] < dep[v]) 48 ans[u] = v; 49 insertVal(prime[i], u); 50 while(tmp % prime[i] == 0) 51 tmp /= prime[i]; 52 } 53 } 54 if(tmp > 1) { 55 int v = findx(tmp); 56 if(dep[ans[u]] < dep[v]) 57 ans[u] =v ; 58 insertVal(tmp, u); 59 } 60 if(nod == 0) 61 l[u] = ++cnt; 62 63 for(int i = 0; i < g[u].size(); i++) { 64 int v = g[u][i]; 65 if(v == fa) 66 continue; 67 if(nod == 0) 68 dep[v] = dep[u]+1; 69 if(all || nod == u || l[v] <= pos && pos <= r[v]) 70 dfs(v, pos, all||nod == u, nod, u); 71 } 72 if(nod == 0) 73 r[u] = cnt; 74 tmp = val[u]; 75 for(int i = 0; i < prime.size() && prime[i] * prime[i] <= tmp; i++) { 76 if(tmp % prime[i] == 0) { 77 deleteVal(prime[i]); 78 while(tmp % prime[i] == 0) 79 tmp /= prime[i]; 80 } 81 } 82 if(tmp > 1) { 83 deleteVal(tmp); 84 } 85 } 86 int main() { 87 88 pre(); 89 dep[1] =1; 90 scanf("%d%d", &n, &q); 91 for(int i = 1; i <= n; i++) 92 scanf("%d", &val[i]); 93 for(int i = 0; i < n-1; i++) { 94 int u, v; 95 scanf("%d%d", &u, &v); 96 g[u].pb(v); 97 g[v].pb(u); 98 } 99 dfs(1, 1, 1, 0, 1); 100 while(q--) { 101 int type; 102 scanf("%d", &type); 103 if(type == 1) { 104 int v; 105 scanf("%d", &v); 106 cout<<(ans[v] ? ans[v] : -1)<<endl; 107 } else { 108 int u, v; 109 scanf("%d%d", &u, &v); 110 val[u] = v; 111 dfs(1, l[u], 0, u, 1); 112 } 113 } 114 return 0; 115 }