51nod 联训1
http://www.51nod.com/Contest/ProblemList.html#contestId=975&randomCode=152804
A
行和列可以分开考虑, 答案是修改行未修改列+修改列未修改行
注意1既不是质数也不是合数
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N = 1e5+10, TR = 4 * N;
int cpri[N], ccom[N];
int pri[N];
bool npri[N];
void sieve(int len){
for(int i = 2; i <= len; ++i){
if(!npri[i]) pri[++pri[0]] = i;
for(int j = 1; j <= pri[0] && pri[j] * i <= len; ++j){
npri[i * pri[j]] = true;
if(i % pri[j] == 0) break;
}
}
for(int i = 2; i <= len; ++i){
cpri[i] = cpri[i-1] + (!npri[i]);
}
for(int i = 2; i <= len; ++i){
ccom[i] = ccom[i - 1] + npri[i];
}
}
struct segment_tree{
struct node{
int sum1, sum2, laz;
node () {
memset(this, 0, sizeof(*this));
}
node (int sum1_, int sum2_, int laz_): sum1(sum1_), sum2(sum2_), laz(laz_){}
friend node operator +(const node& lhs, const node& rhs){
return {lhs.sum1 + rhs.sum1 ,lhs.sum2 + rhs.sum2 , 0};
}
}tree[TR];
void push_up(int rt){
tree[rt] = tree[rt<<1] + tree[rt<<1|1];
}
void update(int rt, int l, int r){
tree[rt].laz ^= 1;
tree[rt].sum1 = cpri[r] - cpri[l-1] - tree[rt].sum1;
tree[rt].sum2 = ccom[r] - ccom[l-1] - tree[rt].sum2;
}
void push_down(int rt, int l, int r){
int mid = (l + r) >> 1;
if(tree[rt].laz){
update(rt<<1, l, mid);
update(rt<<1|1, mid + 1, r);
tree[rt].laz = 0;
}
}
void modify(int rt, int l, int r, int s, int t){
if(s > t) return;
if(s <= l && r <= t) return update(rt, l, r);
int mid = (l + r) >> 1;
push_down(rt, l, r);
if(s <= mid) modify(rt<<1, l, mid, s, t);
if(t > mid) modify(rt<<1|1, mid + 1, r ,s ,t);
push_up(rt);
}
node query(int rt, int l, int r, int s, int t){
if(s > t) return {};
if(s <= l && r <= t) return {tree[rt].sum1, tree[rt].sum2, 0};
int mid = (l + r) >> 1;
node ret = {};
push_down(rt, l, r);
if(s <= mid) ret = query(rt<<1, l, mid, s, t);
if(t > mid) ret = ret + query(rt<<1|1, mid + 1, r ,s ,t);
return ret;
}
void prt(int rt, int l, int r){
cerr<<rt <<" [" << l <<"," << r << "]" << tree[rt].sum1 <<" " << tree[rt].sum2 << endl;
if(l >= r) return;
int mid = (l + r) >> 1;
push_down(rt, l, r);
prt(rt<<1, l, mid);
prt(rt<<1|1, mid + 1, r);
}
}l, c;
int n, q;
bool revlp, revcp, revlc, revcc;
int revl1, revc1;
signed main(){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> q;
sieve(1e5 + 5);
for(int i = 1; i <= q; ++i){
char opt; int l1, r1, l2, r2, v;
cin >> opt;
if(opt == 'M'){
cin >> l1 >> r1;
if(l1 == 1) ++l1, revl1 ^= 1;
l.modify(1, 1, n, l1, r1);
}else if(opt == 'N'){
cin >> l1 >> r1;
if(l1 == 1) ++l1, revc1 ^= 1;
c.modify(1, 1, n, l1, r1);
}else if(opt == 'P'){
cin >> v;
if(v == 0){
revlp ^= 1;
}else{
revcp ^= 1;
}
}else if(opt == 'R'){
cin >> v;
if(v == 0){
revlc ^= 1;
}else{
revcc ^= 1;
}
}else{
cin >> l1 >> r1 >> l2 >> r2;
segment_tree::node infol = l.query(1, 1, n, l1, r1), infoc = c.query(1, 1, n, l2, r2);
ll cntl =
(revlp ? cpri[r1] - cpri[l1-1] - infol.sum1 : infol.sum1) +
(revlc ? ccom[r1] - ccom[l1-1] - infol.sum2 : infol.sum2);
ll cntc =
(revcp ? cpri[r2] - cpri[l2 - 1] - infoc.sum1:infoc.sum1) +
(revcc ? ccom[r2] - ccom[l2 - 1] - infoc.sum2 : infoc.sum2);
if(l1 == 1)cntl = cntl + revl1;
if(l2 == 1)cntc = cntc + revc1;
cout << cntl * (r2 - l2 + 1 - cntc) + cntc*(r1 - l1 + 1 - cntl)<< endl;
}
}
return 0;
}
C
邻接矩阵的max-add乘法的含义多走一条边,最长路
那么可以倍增求最后一个<M的边数
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 150+10;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n, m;
struct matrix{
ll a[N][N];
matrix(){
memset(a, 0xc0, sizeof(a));
}
friend matrix operator *(const matrix& x, const matrix & y){
matrix z;
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= n; ++j){
for(int k = 1; k <= n; ++k){
z[i][j] = max(z[i][j], x[i][k] + y[k][j]);
}
}
}
return z;
}
ll* operator [](int x){
return a[x];
}
const ll* operator [](int x)const{
return a[x];
}
bool check(){
for(int i = 1; i <= n; ++i){
if(a[1][i] >= m) return true;
}
return false;
}
void prt(){
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= n; ++j){
cerr<<a[i][j] <<" ";
}
cerr<<endl;
}
}
friend matrix operator ^(matrix x, int p){
matrix res;
for(;p;p>>=1){
if(p & 1) res = res * x;
x = x * x;
}
return res;
}
}f[200];
void init(){
memset(f, 0xc0, sizeof(f));
}
void solve(){
cin >> n >> m;
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= n; ++j){
cin >> f[0][i][j];
if(f[0][i][j] == 0) f[0][i][j] = -INF;
}
}
ll cnt = 0;
for(int i = 1; i <= 63; ++i) {
f[i] = f[i-1] * f[i-1];
if(f[i].check()) break;
++cnt;
}
if(f[0].check()){
cout << 1 << endl;
return;
}
matrix ans = f[cnt];
ll stp = 1ll << cnt;
for(int i = cnt - 1; i >= 0; --i){
if((ans * f[i]).check()) continue;
ans = ans * f[i];
stp = stp + (1ll << i);
}
cout << stp + 1 << endl;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T;
cin >> T;
while(T--){
init();
solve();
}
return 0;
}
D
一个点变黑(能更新别人)当且仅当其被别的点达到,而且自己的护盾摧毁,Dijsktra即可
#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
const int N = 3E3+10, E = (7E4 + 10) * 2;
const int INF = 0x3f3f3f3f;
int d[N], des[N], arr[N];
int n, m;
struct graph{
struct edge{
int nxt, to, val;
}e[E];
struct gdge{
int nxt, to;
}g[E];
int elen, heade[N];
int glen, headg[N];
int ind[N];
void inse(int frm, int to, int val){
e[++elen] = {heade[frm], to, val};
heade[frm] = elen;
}
void insg(int frm, int to){
g[++glen] = {headg[frm], to};
headg[frm] = glen;
++ind[to];
}
void dij(int s){
priority_queue<pii, vector<pii>, greater<pii>>q;
memset(d, 0x3f, sizeof(d));
memset(des, 0x3f, sizeof(des));
memset(arr, 0x3f, sizeof(des));
d[s] = des[s] = arr[s] = 0;
q.emplace(0, s);
for(int i = 1; i <= n; ++i){
if(ind[i] == 0) des[i] = 0;
}
while(!q.empty()){
pii frt = q.top();q.pop();
int u = frt.second;
if(frt.first > d[u]) continue;
for(int i = headg[u]; i;i = g[i].nxt){
int v = g[i].to;
--ind[v];
if(ind[v] == 0){
des[v] = d[u];
d[v] = max(des[v], arr[v]);
if(d[v] < INF){
q.emplace(d[v], v);
}
}
}
for(int i = heade[u]; i;i = e[i].nxt){
int v = e[i].to;
if(d[u] + e[i].val < arr[v]){
arr[v] = d[u] + e[i].val;
d[v] = max(des[v], arr[v]);
if(d[v] < INF){
q.emplace(d[v], v);
}
}
}
}
}
}G;
int main(){
ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);
cin >> n >> m;
for(int i = 1; i <= m; ++i){
int u,v,w;cin >> u >> v >> w;
G.inse(u, v, w);
}
for(int i = 1; i <= n; ++i){
int cnt; cin >> cnt;
for(int j = 1; j <= cnt; ++j){
int u;cin >> u;G.insg(u, i);
}
}
G.dij(1);
cout << d[n] << endl;
return 0;
}