BZOJ4383/LuoGuP3588 Pustynia/PUS 线段树建图优化
我会告诉你我看了很久很久才把题目看懂吗???怀疑智商了
原来他给的l,r还有k个数字都是下标...
比如给了一个样例 l, r, k, x1,x2,x3...xk,代表的是一个数组num[l]~num[r],其中有k个数num[x1],num[x2]....num[xk]这k个数都比l~r区间剩下的(下标不是x1...xk)的任何一个数大。题目就是给m个这种信息然后构造一个符合条件的数列
知道了这一点可以发现每一个信息都是一组偏序关系,即num[x1] > l~r区间剩下的数 .....num[xk] > l~r区间剩下的数.当然如果数量级小的话直接就每一个关系建一条边直接拓扑排序就可以了.但是这道题数量实在太大,然后这里就有一种黑科技---线段树建图优化.因为我们可以保证每次建边的时候,num[xi]都是和一个区间相连的(单个点也算一个区间),这样我们可考虑区间这个整体,当然具体代码怎么写没这么简单.
又学到一种黑科技....
1 #include <iostream> 2 #include <string.h> 3 #include <cstdio> 4 #include <vector> 5 #include <queue> 6 #include <math.h> 7 #include <string> 8 #include <algorithm> 9 #include <time.h> 10 11 #define SIGMA_SIZE 26 12 #define lson rt<<1 13 #define rson rt<<1|1 14 #define lowbit(x) (x&-x) 15 #define foe(i, a, b) for(int i=a; i<=b; i++) 16 #define fo(i, a, b) for(int i=a; i<b; i++) 17 #pragma warning ( disable : 4996 ) 18 19 using namespace std; 20 typedef long long LL; 21 inline LL LMax(LL a, LL b) { return a>b ? a : b; } 22 inline LL LMin(LL a, LL b) { return a>b ? b : a; } 23 inline LL lgcd(LL a, LL b) { return b == 0 ? a : lgcd(b, a%b); } 24 inline LL llcm(LL a, LL b) { return a / lgcd(a, b)*b; } //a*b = gcd*lcm 25 inline int Max(int a, int b) { return a>b ? a : b; } 26 inline int Min(int a, int b) { return a>b ? b : a; } 27 inline int gcd(int a, int b) { return b == 0 ? a : gcd(b, a%b); } 28 inline int lcm(int a, int b) { return a / gcd(a, b)*b; } //a*b = gcd*lcm 29 const LL INF = 0x3f3f3f3f3f3f3f3f; 30 const LL mod = 1000000007; 31 const double eps = 1e-8; 32 const int inf = 0x3f3f3f3f; 33 const int maxk = 3e6+5; 34 const int maxn = 1e6+5; 35 36 int cnt, tot; 37 int indexx[maxn], val1[maxn], val2[maxn], x[maxn], in[maxn]; 38 int linjie[maxn]; 39 int n, s, m; 40 queue<int> q; 41 struct node { 42 int to, nnext, len; 43 }pp[maxk]; 44 45 void addedge( int u, int v, int l ) 46 { pp[cnt].to = v; pp[cnt].len = l; pp[cnt].nnext = linjie[u]; linjie[u] = cnt++; in[v]++; } 47 48 49 void build(int rt, int L, int R) 50 { 51 if ( L == R ) 52 { indexx[L] = rt; return; } 53 54 int mid = (L+R)>>1; 55 build(lson, L, mid); 56 build(rson, mid+1, R); 57 addedge(lson, rt, 0); addedge(rson, rt, 0); 58 } 59 60 void update(int rt, int L, int R, int lhs, int rhs, int C) 61 { 62 if ( lhs <= L && rhs >= R ) 63 { 64 addedge(rt, C, 0); 65 return; 66 } 67 68 int mid = (L+R)>>1; 69 if ( lhs <= mid ) update(lson, L, mid, lhs, rhs, C); 70 if ( rhs > mid ) update(rson, mid+1, R, lhs, rhs, C); 71 } 72 73 void init() 74 { 75 cnt = 0; 76 memset(linjie, -1, sizeof(linjie)); 77 build(1, 1, n); tot = n << 2; 78 79 int a, b; 80 while (s--) 81 { 82 scanf("%d %d", &a, &b); 83 val1[indexx[a]] = val2[indexx[a]] = b; 84 } 85 } 86 87 int main() 88 { 89 cin >> n >> s >> m; 90 init(); 91 92 int l, r, k; 93 while (m--) 94 { 95 scanf("%d %d %d", &l, &r, &k); 96 x[0] = l-1; x[k+1] = r+1; tot++; 97 98 foe(i, 1, k) { 99 scanf("%d", &x[i]); 100 addedge(tot, indexx[x[i]], 1); 101 } 102 103 foe(i, 0, k) { 104 if (x[i+1] - x[i] > 1) 105 update(1, 1, n, x[i]+1, x[i+1]-1, tot); 106 } 107 } 108 109 foe(i, 1, tot) 110 if (!in[i]) { 111 val1[i] = Max(val1[i], 1); 112 q.push(i); 113 } 114 115 int a, b; 116 while (!q.empty()) 117 { 118 a = q.front(); q.pop(); 119 for (int i = linjie[a]; ~i; i = pp[i].nnext) { 120 val1[pp[i].to] = Max(val1[pp[i].to], val1[a]+pp[i].len); 121 in[pp[i].to] --; 122 123 if (val2[pp[i].to] && val1[pp[i].to] > val2[pp[i].to]) { 124 printf("NIE\n"); 125 return 0; 126 } 127 if ( !in[pp[i].to] )q.push(pp[i].to); 128 } 129 } 130 131 foe(i, 1, n) 132 if ( !val1[indexx[i]] || val1[indexx[i]] > 1000000000) 133 { printf("NIE\n"); return 0; } 134 135 printf("TAK\n"); 136 fo(i, 1, n) 137 printf("%d ", val1[indexx[i]]); 138 printf("%d\n", val1[indexx[n]]); 139 return 0; 140 }
什么时候能够不再这么懒惰