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;
}
posted @ 2022-08-08 21:44  CDsidi  阅读(40)  评论(0编辑  收藏  举报