zoukankan      html  css  js  c++  java
  • 9.25李赛 挂成狗了 & 被打爆了

    挂成狗了。

    A LOJ #6720. 「CodePlus #7」最小路径串

    对于每一个点的出边按照到达点的编号大小排序。

    dfs 一下。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #define pb emplace_back
    typedef long long ll;
    typedef std::vector<int> veci;
    const ll mod = 998244353;
    const int N = 1000010;
    int n, m, ent, head[N];
    ll dis[N];
    bool vis[N];
    char ch[N*12];
    veci eg[N];
    int to_int(int l, int r) {
    	int w = 0;
    	for(int i = l; i <= r; ++i) w = w * 10 + (ch[i] - '0');
    	return w;
    }
    void dfs(int x, int f) {
    	vis[x] = 1; dis[x] = (dis[f] * 1000000 % mod + x) % mod;
    	std::sort(eg[x].begin(), eg[x].end());
    	for(auto v : eg[x]) if(!vis[v]) dfs(v, x);
    }
    signed main() {
    	scanf("%d%d", &n, &m);
    	scanf("%s", ch+1);
    	for(int i = 1; i <= 12 * m; i += 12) {
    		int x = to_int(i, i+5), y = to_int(i+6, i+11);
    		eg[x].pb(y); eg[y].pb(x);
    	}
    	dfs(0, 0);
    	for(int i = 1; i < n; ++i) printf("%lld
    ", !vis[i] ? -1ll : dis[i]);
    	return 0;
    }
    

    B LOJ #2743. 「JOI Open 2016」摩天大楼

    麻了,这题为什么在第二题,卡常卡吐了。还忘了判 n=1

    排下序,易得 dp:(f_{i,j,k,0/1,0/1}) 表示考虑前 (i) 个数,有 (j) 个连续段,费用为 (k),左/右的顶端有没有填掉。

    这样 (k) 的枚举范围大概是个 (2sum a),但实际上可以再紧一紧,然后滚动数组,用 vector 卡卡空间,就这样 (mathcal{O}(n^3a)) 在LOJ上卡过去了...

    优化到 (mathcal{O}(n^2L)) 的话,考虑费用提前计算,这样的话向后转移 (k) 是不降的,(k) 的枚举范围就到 (L) 就可以了。

    代码是 (mathcal{O}(n^3a)) 的做法。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #define pb emplace_back
    typedef long long ll;
    const ll mod = 1000000007;
    ll Add(ll x, ll y) { return (x + y >= mod) ? (x + y - mod) : (x + y); }
    ll Mul(ll x, ll y) { return x * y % mod; }
    ll Mod(ll x) { return (x >= mod) ? (x - mod) : (x < 0 ? (x + mod) : x); }
    inline ll cadd(int &x, ll y) { return x = (x + y >= mod) ? (x + y - mod) : (x + y); }
    template <typename T> T Max(T x, T y) { return x > y ? x : y; }
    template <typename T> T Min(T x, T y) { return x < y ? x : y; }
    template <typename T>
    T &read(T &r) {
    	r = 0; bool w = 0; char ch = getchar();
    	while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
    	while(ch >= '0' && ch <= '9') r = r * 10 + (ch ^ 48), ch = getchar();
    	return r = w ? -r : r;
    }
    const int N = 101;
    const int L = 1001;
    int n, l, a[N], sum, all, lim;
    int len[N][2][2];
    std::vector<int> f[N][2][2], g[N][2][2];
    int cmp(int x, int y) { return x > y; }
    signed main() {
    	read(n); read(l);
    	if(n == 1) {
    		puts("1");
    		return 0;
    	}
    	for(int i = 1; i <= n; ++i) read(a[i]), all += a[i];
    	std::sort(a + 1, a + n + 1, cmp);
    	for(int i = 0; i <= n; ++i)
    		for(int p1 = 0; p1 <= 1; ++p1)
    			for(int p2 = 0; p2 <= 1; ++p2)
    				f[i][p1][p2].pb(0), f[i][p1][p2].pb(0),
    				g[i][p1][p2].pb(0), g[i][p1][p2].pb(0);
    	f[0][0][0][0] = 1;
    	for(int o = 1; o <= n; ++o) {
    		sum += a[o]; lim = Min(sum, l + 2 * (all - sum) + 2*a[o]);
    		for(int i = 0; i <= o; ++i)
    			for(int p1 = 0; p1 <= 1; ++p1)
    				for(int p2 = 0; p2 <= 1; ++p2)
    					while(len[i][p1][p2] <= 2*lim)
    						f[i][p1][p2].pb(0), g[i][p1][p2].pb(0), ++len[i][p1][p2];
    		for(int i = 0; i < o; ++i)
    			for(int j = 0; j <= 2*(lim-a[o]); ++j) 
    				for(int p1 = 0; p1 <= 1; ++p1)
    					for(int p2 = 0; p2 <= 1; ++p2) {
    						if(!f[i][p1][p2][j]) continue ;
    						cadd(g[i+1][p1][p2][j+2*a[o]], 1ll * f[i][p1][p2][j] * (i+1-p1-p2) % mod); //新开一个连通块 且不在左/右 
    						if(!p1) cadd(g[i+1][1][p2][j+a[o]], 1ll * f[i][p1][p2][j]); //新开一个连通块 在左
    						if(!p2) cadd(g[i+1][p1][1][j+a[o]], 1ll * f[i][p1][p2][j]); //新开一个连通块 在右
    						if(i) cadd(g[i][p1][p2][j], 1ll * f[i][p1][p2][j] * (2*i-p1-p2) % mod); //连上之前一个连通块 且不在左/右
    						if(!p1 && i) cadd(g[i][1][p2][j-a[o]], 1ll * f[i][p1][p2][j]); //连上之前一个连通块 在左
    						if(!p2 && i) cadd(g[i][p1][1][j-a[o]], 1ll * f[i][p1][p2][j]); //连上之前一个连通块 在右
    						if(i>=2) cadd(g[i-1][p1][p2][j-2*a[o]], 1ll * f[i][p1][p2][j] * (i-1) % mod);//连接两个联通块
    					}
    		for(int i = 0; i <= o; ++i)
    			for(int j = 0; j <= 2*lim; ++j)
    				for(int p1 = 0; p1 <= 1; ++p1)
    					for(int p2 = 0; p2 <= 1; ++p2)
    						f[i][p1][p2][j] = g[i][p1][p2][j],
    						g[i][p1][p2][j] = 0;
    	}
    	int ans = 0;
    	while(len[1][1][1] <= l) f[1][1][1].pb(0), ++len[1][1][1];
    	for(int i = 0; i <= Min(l, len[1][1][1]); ++i) {
    		cadd(ans, 1ll*f[1][1][1][i]);
    	}
    	printf("%d
    ", ans);
    	return 0;
    }
    

    C LOJ #6723. 「CodePlus #7」教科书般的亵渎 / Luogu P5068 [Ynoi2015] 我回来了

    麻了,本来是能切掉这个简单的Ynoi题的,但是看错 (0) 的个数,数组开小了...咋还能这样挂分的...

    每个伤害值 (d) 可以分开考虑,那就考虑它在哪个时刻,对答案的贡献加了个 (1),这些总和是个调和级数 (mathcal{O}(nlog n)) 的。

    离线下来,对于每个值记录它最早在哪个时刻加入,用个线段树 / ST表查询区间最小值,对于每一个 (d) 暴力枚举 ([1,d],[d+1,2d]...),然后看区间最小值,再做个前缀 (max),就知道具体是在哪个时刻答案 (+1) 了。

    最后统计答案的时候用个树状数组,支持单点 (+1),查询区间和就可以了,修改次数是 (mathcal{O}(nlog n)),查询是 (mathcal{O}(m)) 的。

    总复杂度是 (mathcal{O}(nlog^2n+mlog n)) 的。

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #define pb push_back
    typedef long long ll;
    template <typename T> T Max(T x, T y) { return x > y ? x : y; }
    template <typename T> T Min(T x, T y) { return x < y ? x : y; }
    template <typename T>
    T &read(T &r) {
    	r = 0; bool w = 0; char ch = getchar();
    	while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
    	while(ch >= '0' && ch <= '9') r = r * 10 + (ch ^ 48), ch = getchar();
    	return r = w ? -r : r;
    }
    inline int lowbit(int x) { return x & (-x); }
    const int N = 1000010;
    const int INF = 0x7fffffff;
    int n, m;
    int b[N];
    std::vector<int>vec[N]; 
    namespace Segment_Tree {
    	#define ls tree[x].lson
    	#define rs tree[x].rson
    	#define tl tree[x].l
    	#define tr tree[x].r
    	int trnt;
    	struct SGT {
    		int l, r, mn, lson, rson;
    	}tree[N << 1];
    	inline void pushup(int x) { tree[x].mn = Min(tree[ls].mn, tree[rs].mn); }
    	int build(int l, int r) {
    		int x = ++trnt; tl = l; tr = r;
    		if(l == r) {
    			tree[x].mn = b[l];
    			return x;
    		}
    		int mid = (l + r) >> 1;
    		ls = build(l, mid); rs = build(mid+1, r);
    		pushup(x);
    		return x;
    	}
    	int query(int x, int l, int r) {
    		if(tl >= l && tr <= r) return tree[x].mn;
    		int mid = (tl + tr) >> 1, sumq = INF;
    		if(mid >= l) sumq = Min(sumq, query(ls, l, r));
    		if(mid < r) sumq = Min(sumq, query(rs, l, r));
    		return sumq;
    	}
    	#undef ls
    	#undef rs
    	#undef tl
    	#undef tr
    }
    using namespace Segment_Tree;
    int opt[N], l[N], r[N], h[N], t[N];
    int tr[N];
    void modify(int x, int v) { for(; x <= n; x += lowbit(x)) tr[x] += v; }
    int query(int x) { int sumq = 0; for(; x; x -= lowbit(x)) sumq += tr[x]; return sumq; }
    int qsum(int l, int r) { return query(r) - query(l-1); }
    signed main() {
    	read(n); read(m);
    	for(int i = 1; i <= n; ++i) b[i] = INF;
    	for(int i = 1; i <= m; ++i) {
    		read(opt[i]);
    		if(opt[i] == 1) read(h[i]), b[h[i]] = Min(b[h[i]], i);
    		else read(l[i]), read(r[i]);
    	}
    	build(1, n);
    	for(int i = 1; i <= n; ++i) {
    		for(int j = 1; (j-1)*i < n; ++j) {
    			t[j] = query(1, (j-1)*i+1, Min(j*i, n));
    			if(t[j] == INF) break ;
    		}
    		for(int j = 1; (j-1)*i < n; ++j) {
    			if(t[j] == INF) break ;
    			t[j] = Max(t[j], t[j-1]);
    			vec[t[j]].pb(i);
    		}
    	}
    	for(int i = 1; i <= m; ++i) {
    		for(auto x : vec[i]) modify(x, 1);
    		if(opt[i] == 2) {
    			printf("%d
    ", r[i]-l[i]+1 + qsum(l[i], r[i]));
    		}
    	}
    	return 0;
    }
    

    D LOJ #2350. 「JOI 2018 Final」月票购买

    不会做,被打爆了...

    考虑找出在 (S o T) 最短路上的边,形成个 DAG(正反方向都可以),两种方向分别考虑。

    结论是 (U o V) 的路径如果和 (S o T) 的最短路相交,则仅有一段相交,因为如果有两段的话,显然中间断开的路走 (S o T) 的最短路更优。

    那就在 DAG 上拓扑排序 / dfs,对于每个点记录能走到它的点(或者它能走到的点)的 (dis(U,y),dis(V,y)) 的最小值,分别记作 (f_x,g_x),答案即为 (min{f_x+dis(V,x),g_x+dis(U,x),dis(U,V)})

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #define mp std::make_pair
    #define fir first
    #define sec second
    typedef long long ll;
    typedef std::pair<ll, int> pli;
    template <typename T> T Max(T x, T y) { return x > y ? x : y; }
    template <typename T> T Min(T x, T y) { return x < y ? x : y; }
    template <typename T>
    T &read(T &r) {
    	r = 0; bool w = 0; char ch = getchar();
    	while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
    	while(ch >= '0' && ch <= '9') r = r * 10 + (ch ^ 48), ch = getchar();
    	return r = w ? -r : r;
    }
    const int N = 100010;
    const ll INF = 0x7fffffffffffffff;
    int n, m, S, T, U, V;
    int ent = 1, head[N], pre[N];
    ll dS[N], dT[N], dU[N], dV[N], f[N], g[N], ans;
    bool vis[N];
    struct Egde {
    	int to, val, nxt;
    }e[N<<2];
    inline void add(int x, int y, int z) {
    	e[++ent].to = y; e[ent].val = z; e[ent].nxt = head[x]; head[x] = ent;
    }
    void Dij(int s, ll *dis) {
    	for(int i = 1; i <= n; ++i) vis[i] = 0, dis[i] = INF;
    	dis[s] = 0;
    	std::priority_queue<pli>q;
    	q.push(mp(0, s));
    	while(!q.empty()) {
    		int x = q.top().sec; q.pop();
    		if(vis[x]) continue ;
    		vis[x] = 1;
    		for(int i = head[x]; i; i = e[i].nxt) {
    			int v = e[i].to;
    			if(dis[v] > dis[x] + e[i].val) {
    				dis[v] = dis[x] + e[i].val;
    				q.push(mp(-dis[v], v));
    			}
    		}
    	}
    }
    void dfs(int x) {
    	if(vis[x]) return ;
    	vis[x] = 1; f[x] = dU[x]; g[x] = dV[x];
    	for(int i = head[x]; i; i = e[i].nxt) {
    		int v = e[i].to;
    		if(dS[x] + dT[v] + e[i].val != dS[T]) continue ;
    		dfs(v);
    		f[x] = Min(f[x], f[v]); g[x] = Min(g[x], g[v]);
    	}
    	ans = Min(ans, Min(f[x] + dV[x], g[x] + dU[x]));
    }
    signed main() {
    	read(n); read(m);
    	read(S); read(T);
    	read(U); read(V);
    	for(int i = 1; i <= m; ++i) {
    		int u, v, w; read(u); read(v); read(w);
    		add(u, v, w);
    		add(v, u, w);
    	}
    	Dij(S, dS); Dij(T, dT); Dij(U, dU); Dij(V, dV); ans = INF;
    	for(int i = 1; i <= n; ++i) f[i] = g[i] = 0x3f3f3f3f3f3f3f3f, vis[i] = 0;
    	dfs(S);
    	ans = Min(ans, dU[V]);
    	printf("%lld
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    图片移动特效
    风云舞
    弹出页面
    javascript放大镜原版
    jquery UI入门
    AJAX demo——操作文本文件
    上一页 1 2 ...10 下一页 百度 GOOGLE 分页
    在后台调用JavaScript打开新页面
    Ext简介
    My97DatePicker
  • 原文地址:https://www.cnblogs.com/do-while-true/p/15334435.html
Copyright © 2011-2022 走看看