• 二分套二分+贪心:CSPS2023T4


    二分答案

    再二分出每个点最晚什么时候被选

    然后按照最晚被选的时间从前往后贪心

    暴力跳即可

    复杂度 O ( n log ⁡ 2 n ) O(n\log^2n) O(nlog2n)

    #include
    using namespace std;
    #define int __int128
    #define ll long long
    //#define int long long
    inline int read() {
    	int x = 0, f = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9') {
    		if(ch == '-') f = -1;
    		ch = getchar();
    	}
    	while(ch>='0' && ch<='9') {
    		x = (x<<1) + (x<<3) +(ch^48);
    		ch=getchar();
    	}
    	return x * f;
    }
    void print(int a) {
    	if(a/10) print(a/10); 
    	putchar(a%10+'0'); 
    }
    ll zh(int a) {
    	if(a/10) return zh(a/10)*10+(ll)(a%10); 
    	return (ll)(a%10); 
    }
    #define pb push_back
    #define N 200010
    //#define M
    //#define mo
    struct node {
    	int a, b, c, id, d; 
    }a[N];
    int ceil(int a, int b) {
    	return a / b + (a % b ? 1 : 0); 
    }
    int n, m, i, j, k, T, flg, u, v, f[N], w[N], p[N];
    vector<int>G[N]; 
    
    void dfs(int x, int fa)  {
    	f[x] = fa; 
    	for(auto y : G[x]) 
    		if(y != fa) dfs(y, x); 
    }
    
    int S(int l, int r, int n) {
    	return (l + r) * n / 2; 
    }
    	
    namespace Sol {
    	int l, r, mid, s, t, i, j, vis[N]; 
    	int suan(int i, int l) { //节点i从第r天到第l天 
    		if(l == 0) return a[i].b; 
    		if(a[i].c < 0) {
    			if(l < p[i]) {
    				int	shou = a[i].b; 
    				int	mo = a[i].b + l * a[i].c; 
    				return S(shou, mo, l+1); 
    			} 
    			if(l >= p[i]) return w[i]+(l-p[i]+1); 
    		}
    		else {
    			int	shou = a[i].b; 
    			int	mo = a[i].b + l * a[i].c; 
    			return S(shou, mo, l+1); 
    		}
    	}
    	int check(int k) {
    //		printf("Check : %lld\n", zh(k)); 
    		sort(a+1, a+n+1, [] (node x, node y) { return x.id < y.id; }); 
    		for(i=1; i<=n; ++i) {
    			l = 1; r = k; 
    //			if(k==31) printf("%lld %lld\n", zh(suan(i, k)), zh(suan(i, 0))); 
    			if(suan(i, k) - suan(i, 0) < a[i].a) return 0; 
    			while(l < r) {
    				mid = (l+r+1)>>1; 
    //				printf("%lld [%lld %lld] : %lld %lld %lld\n", i, k, mid, suan(i, k), suan(i, mid-1), suan(i, k) - suan(i, mid-1)); 
    				if(suan(i, k) - suan(i, mid-1) >= a[i].a) l=mid; 
    				else r=mid-1; 
    			}
    			a[i].d=l; //最晚在第d天点亮 
    			printf("last %lld : %lld\n", zh(i), zh(a[i].d)); 
    		}
    		sort(a+1, a+n+1, [] (node x, node y) { return x.d < y.d; }); 
    		memset(vis, 0, sizeof(vis)); 
    		vis[1] = j = 1; 
    		for(i=1; i<=n; ++i) {
    			int x = a[i].id; 
    			if(!vis[x]) {
    				int y = x; 
    				while(!vis[y]) y = f[y], ++j; 
    				vis[x] = j; y = x; 
    				while(!vis[f[y]]) vis[f[y]]=vis[y]-1, y=f[y]; 
    			}
    //			printf("vis[%lld] = %lld\n", zh(x), zh(vis[x])); 
    			if(vis[x] > a[i].d) return 0; 
    		}
    //		printf("OK ! \n"); 
    		return 1; 
    	}
    }
    
    signed main() {
    //	freopen("tree.in", "r", stdin);
    //	freopen("tree.out", "w", stdout);
    //	freopen("in.txt", "r", stdin);
    //	freopen("out.txt", "w", stdout);
    //	srand(time(0));
    //	T=read();
    //	while(T--) {
    //	}
    	n=read(); 
    	for(i=1; i<=n; ++i)  {
    		a[i].id=i; 
    		a[i].a=read(); a[i].b=read(); a[i].c=read(); 
    	}
    	for(i=1; i<n; ++i) {
    		u=read(); v=read(); 
    		G[u].pb(v); G[v].pb(u); 
    	}
    	dfs(1, 0); 
    	int l, r, mid; 
    	for(i=1; i<=n; ++i)  
    		if(a[i].c < 0)  {
    			l = a[i].b / (-a[i].c) ; 
    			for(j = l-3; j <= l+3; ++j) 
    				if(a[i].b + j *a[i].c < 1) break; 
    			p[i] = j ; // 从第p[i]天开始出事 
    			int shou = a[i].b, mo = a[i].b + (j-1)*a[i].c; 
    			w[i] = S(shou, mo, j); 
    //			printf("%lld : %lld | %lld\n", zh(i), zh(p[i]), zh(w[i])) ;
    		}
    	l=n; r=1e9; 
    	while(l < r) {
    		mid = (l + r) >> 1; 
    		if(Sol::check(mid)) r = mid; 
    		else l = mid + 1; 
    	}
    	print(l); 
    //	printf("%lld", l); 
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
  • 相关阅读:
    LeetCode【1. 两数之和】
    C# 什么是继承和派生
    CDH CDH 13Cloudera Manager Console FreeIPA 用户规划(markdown新版)
    【Node.js】—基本知识点总结
    口袋参谋:生意参谋指数转换工具,比对手更了解对手!
    头歌——Linux——下的 c 编程
    SpringBoot笔记:SpringBoot集成MyBatis实战
    使用对比学习处理大规模多模态单细胞数据
    【HDLBits 刷题 10】Circuits(6)Finite State Manchines 10-17
    【安卓逆向】去除云注入(使用MT论坛dl的方法总结拓展)
  • 原文地址:https://blog.csdn.net/zhangtingxiqwq/article/details/133991517