首页 > 代码库 > Codeforces Round #264 (Div. 2)

Codeforces Round #264 (Div. 2)

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 oout18 #define  inout in out19 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 }
View Code

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 oout18 #define  inout in out19 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 }
View Code

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:>>>>>\n", (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 }
View Code

 

Codeforces Round #264 (Div. 2)