2017 多校联合训练 9 题解

Problem 1001

Problem 1002

考虑把每个询问拆分成2个单独的询问。

拆分后的询问为(s, t, x)。

也就是询问从s到t的最短路上所有权值小于等于x的点的权值总和。

我们把(s, t, a, b)拆成(s, t, a - 1) 和(s, t, b)。

那么第二个询问减去第一个询问的答案就是原来这个询问的答案。

我们把这2m个询问离线,以x为关键字升序排序。

这棵树的初始状态:所有点的权值都为0。

然后依次处理每个询问,先看有哪些点的权值小于等于当前询问的x值。

我们要保证当前所有满足条件的点都已经被更新到树上,如果还没更新就需要更新。

已经更新的不需要更新。

同时那些不满条件的点不在树上。

这个过程用双指针维护即可(但比赛的时候我为了省时间直接写了二分)

这样更新的总次数为n。

更新和查询用树链剖分维护就可以了。

时间复杂度$O(nlog^{2}(n) + mlogm + mlogn)$  (我的程序的复杂度)

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)
#define lson		i << 1, L, mid
#define rson		i << 1 | 1, mid + 1, R


typedef long long LL;

const int N = 1e5 + 10;

struct query_node{
	int x, y;
	LL a, b;
} q[N];

struct query_Node{
	int x, y;
	LL val;
	int id;
	LL ans;
	friend bool operator < (const query_Node &a, const query_Node &b){
		return a.val < b.val;
	}
} qu[N << 1];

struct Val{
	int id;
	LL val;
	friend bool operator < (const Val &a, const Val &b){
		return a.val < b.val;
	}
} num[N];

vector <int> v[N];
int son[N], father[N], sz[N], deep[N], top[N], f[N], fp[N];
int n, m, cnt, tot, upnow;
LL  a[N], ret[N], Num[N], sum[N << 2];

bool cmp(const query_Node &a, const query_Node &b){
	if (a.id != b.id) return a.id < b.id;
	else return a.val < b.val;
}

void dfs1(int x, int fa, int dep){
	deep[x] = dep;
	father[x] = fa;
	son[x] = 0;
	sz[x] = 1;
	for (auto u : v[x]){
		if (u == fa) continue;
		dfs1(u, x, dep + 1);
		sz[x] += sz[u];
		if (sz[son[x]] < sz[u]) son[x] = u;
	}
}

void dfs2(int x, int tp){
	top[x] = tp;
	f[x] = ++tot;
	fp[f[x]] = x;
	if (son[x]) dfs2(son[x], tp);
	for (auto u : v[x]){
		if (u == father[x] || u == son[x])  continue;
		dfs2(u, u);
	}
}

inline void pushup(int i){
	sum[i] = sum[i << 1] + sum[i << 1 | 1];
}


void update(int i, int L, int R, int pos, LL val){
	if (L == R && L == pos){
		sum[i] = val;
		return ;
	}

	int mid = (L + R) >> 1;
	if (pos <= mid) update(lson, pos, val);
	if (pos > mid)  update(rson, pos, val);
	pushup(i);
}


LL query_sum(int i, int L, int R, int l, int r){
	if (L == l && R == r) return sum[i];
	int mid = (L + R) >> 1;
	if (r <= mid) return query_sum(lson, l, r);
	else if (l > mid) return query_sum(rson, l, r);
	else return query_sum(lson, l, mid) + query_sum(rson, mid + 1, r);
}


LL find_sum(int x, int y){
	int f1 = top[x], f2 = top[y];
	LL ret = 0;
	for (; f1 != f2; ){
		if (deep[f1] < deep[f2]) swap(f1, f2), swap(x, y);
		ret += query_sum(1, 1, n, f[f1], f[x]);
		x = father[f1], f1 = top[x];
	}

	if (x == y) return ret + query_sum(1, 1, n, f[x], f[y]);
	if (deep[x] > deep[y]) swap(x, y);
	return ret + query_sum(1, 1, n, f[x], f[y]);
}

int main(){

	while (~scanf("%d%d", &n, &m)){
		rep(i, 1, n) scanf("%lld", a + i);
		rep(i, 0, n + 1) v[i].clear();
		rep(i, 2, n){
			int x, y;
			scanf("%d%d", &x, &y);
			v[x].push_back(y);
			v[y].push_back(x);
		}

		cnt = 0;

		rep(i, 1, m){
			scanf("%d%d%lld%lld", &q[i].x, &q[i].y, &q[i].a, &q[i].b);
			++cnt;
			qu[cnt].x = q[i].x;
			qu[cnt].y = q[i].y;
			qu[cnt].val = q[i].a - 1LL;
			qu[cnt].id = i;
			++cnt;
			qu[cnt].x = q[i].x;
			qu[cnt].y = q[i].y;
			qu[cnt].val = q[i].b;
			qu[cnt].id = i;
		}

		sort(qu + 1, qu + cnt + 1);

		tot = 0;
		dfs1(1, 0, 0);
		dfs2(1, 1);	

		rep(i, 1, n) num[i].val = a[i], num[i].id = i;
		sort(num + 1, num + n + 1);
		rep(i, 1, n) Num[i] = num[i].val;

		memset(sum, 0, sizeof sum);

		upnow = 0;
		rep(i, 1, cnt){
			int pos = upper_bound(Num + 1, Num + n + 1, qu[i].val) - Num - 1;
			rep(j, upnow + 1, pos){
				update(1, 1, n, f[num[j].id], num[j].val);
			}

			qu[i].ans = find_sum(qu[i].x, qu[i].y);
			upnow = pos;
		}

		sort(qu + 1, qu + cnt + 1, cmp);

		rep(i, 1, m) ret[i] = qu[i * 2].ans - qu[i * 2 - 1].ans;
		rep(i, 1, m - 1) printf("%lld ", ret[i]);
		printf("%lld
", ret[m]);
		

	}

	return 0;
}

Problem 1003

Problem 1004

Problem 1005

这道题我知道的有两种做法。

一个是缩点为DAG,则如果在拓扑序中出现了有两个及以上入度为0的点则不合法。

另一种是用bitset优化Floyd。

因为边数只有6000,所以不会TLE。

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)

const int N = 1e3 + 10;
int n, m;
bitset <N> f[N];
bool fl;
int T;


int main(){

	scanf("%d", &T);
	while (T--){
		scanf("%d%d", &n, &m);
		rep(i, 0, n + 1) f[i].reset();
		rep(i, 1, m){
			int x, y;
			scanf("%d%d", &x, &y);
			f[x][y] = 1;
		}

		rep(i, 1, n) rep(j, 1, n) if (f[j][i]) f[j] |= f[i];
		fl = true;
		rep(i, 1, n - 1){
			rep(j, i + 1, n){
				if (!(f[i][j] || f[j][i])){
					fl = false;
					break;
				}
			}
			if (!fl) break;
		}

		puts(fl ? "I love you my love and our love save us!" : "Light my fire!");
	}


	return 0;
}

Problem 1006

Problem 1007

Problem 1010

比赛时居然这题会卡这么长时间

一开始以为之前有类似的题 直接模拟就行

后来发现这题数据范围比之前那题大
因此需要用dp进行转移

另外 这题细节较多 需要注意

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstdlib>
  5 #include<algorithm>
  6 #include<cstring>
  7 #include<string>
  8 #include<vector>
  9 #include<map>
 10 #include<set>
 11 #include<queue>
 12 using namespace std;
 13 bool matchTmp(char *str, char *pattern){
 14     if(*str=='' && *pattern=='') return true;
 15     if(*str!='' && *pattern=='') return false;
 16     if(*(pattern+1)=='*'){
 17         if(*pattern==*str || (*pattern=='.'&&*str!=''))
 18         {
 19             bool b1= matchTmp(str+1,pattern+2);
 20             bool b2= matchTmp(str,pattern+2);
 21             if (b1||b2) return true;
 22             pattern[0]=str[0];
 23             return  matchTmp(str+1,pattern);
 24 
 25             //return matchTmp(str+1,pattern+2)
 26             //|| matchTmp(str+1,pattern)
 27             //|| matchTmp(str,pattern+2);
 28         }
 29         else return matchTmp(str,pattern+2);
 30     }
 31     if(*str==*pattern || (*pattern=='.'&&*str!=''))
 32         return matchTmp(str+1,pattern+1);
 33     return false;
 34 }
 35 char s1[2510],s2[2510];
 36 pair<char,int> pipei[2510];
 37 bool fg[2510];
 38 int dp[2510][2];
 39 int main()
 40 {
 41     int _;
 42     scanf("%d",&_);
 43     while (_--)
 44     {
 45         scanf("%s",s1);
 46         scanf("%s",s2);
 47         int len1=strlen(s1),len2=strlen(s2);
 48         int pos=0,cnt=0;
 49         while (pos<len2)
 50         {
 51             if (pos+2<len2&&s2[pos]>='a'&&s2[pos]<='z'&&s2[pos+1]=='*')
 52             {
 53                 //pipei[++cnt]={s2[pos],1};
 54                 char c=s2[pos];
 55                 pos+=2;
 56                 int tot=0,tt=0;
 57                 while (pos<len2&&(s2[pos]==c||s2[pos]=='*'))
 58                 {
 59                     pos++;
 60                     tot++;
 61                     if (s2[pos]=='*') tt++;
 62                 }
 63                 pipei[++cnt]={c,tot-tt*2};
 64                 fg[cnt]=0;
 65             }
 66             else if (pos+1<len2&&s2[pos+1]=='*')
 67             {
 68                 pipei[++cnt]={s2[pos],0};
 69                 fg[cnt]=0;
 70                 pos+=2;
 71             }
 72             else if (s2[pos]>='a'&&s2[pos]<='z')
 73             {
 74                 char c=s2[pos];
 75                 int tot=0,tt=0;
 76                 bool nd=false;
 77                 while (pos<len2&&(s2[pos]==c||s2[pos]=='*'))
 78                 {
 79                     pos++;
 80                     tot++;
 81                     if (s2[pos]=='*') tt++,nd=true;
 82                 }
 83                 pipei[++cnt]={c,tot-tt*2};
 84                 fg[cnt]=1;
 85                 if (nd) fg[cnt]=0;
 86             }
 87             else
 88             {
 89                 pos++;
 90                 pipei[++cnt]={'.',1};
 91                 fg[cnt]=1;
 92             }    
 93         }
 94         bool can=true;
 95         int i,j;
 96         //int mi=0,ma=0;
 97         for (i=1;i<=cnt;i++)
 98         {
 99             dp[i][0]=999899;
100             dp[i][1]=0;
101         }
102         for (i=1;i<=cnt;i++)
103         {
104             bool used=false;
105             for (j=dp[i-1][0];j<=dp[i-1][1];j++)
106             {
107                 if (fg[i])
108                 {
109                     //cout<<i<<" "<<j<<endl;
110                     int pos=j;
111                     char c=pipei[i].first;
112                     if (c=='.') c=s1[pos];
113                     int tt=0;
114                     //if (i==6) cout<<s1[j]<<endl;
115                     //if (i==4&&j==22) cout<<pos<<" "<<s1[pos]<<endl;
116                     while (pos<len1&&s1[pos]==c)
117                     {
118                         pos++;
119                         tt++;
120                         if (tt==pipei[i].second) break;
121                     }
122                     if (tt==pipei[i].second)
123                     {
124                         used=true;
125                         dp[i][0]=min(dp[i][0],pos);
126                         dp[i][1]=max(dp[i][1],pos);
127                         //cout<<i<<" "<<j<<" "<<dp[i][0]<<" "<<dp[i][1]<<endl;
128                     }
129                 }
130                 else
131                 {
132                     char c=pipei[i].first;
133                     bool fg2=false;
134                     int pos=j;
135                     if (c=='.')
136                     {
137                         c=s1[pos];
138                         fg2=true;
139                     }
140                     int tt=0;
141                     if (pipei[i].second==0)
142                     {
143                         used=true;
144                         //cout<<i<<" "<<used<<endl;
145                         dp[i][0]=min(dp[i][0],pos);
146                         dp[i][1]=max(dp[i][1],pos);
147 
148                     }
149                     while (pos<len1&&s1[pos]==c)
150                     {
151                         //pos++;
152                         //tt++;
153                         //cout<<tt<<" "<<pipei[i].second<<endl;
154                         pos++;
155                         tt++;
156                         if (tt>=pipei[i].second)
157                         {
158                             used=true;
159                             dp[i][0]=min(dp[i][0],pos);
160                             dp[i][1]=max(dp[i][1],pos);
161                             //cout<<i<<" "<<dp[i][0]<<" "<<dp[i][1]<<endl;
162                             //cout<<"hhhhhhh"<<" "<<pos<<endl;
163                         }
164                         //pos++;
165                         //tt++;
166 
167                     }
168                 }
169             }
170             if (!used||dp[i][0]>dp[i][1])
171             {
172               
173                 //cout<<i<<" "<<used<<endl;
174                 can=false;
175                 break;
176             }
177              //cout<<i<<" "<<dp[i][0]<<" "<<dp[i][1]<<" "<<s1[dp[i][0]]<<" "<<s1[dp[i][1]]<<endl;
178         }
179     //    for (i=1;i<=cnt;i++)
180     //        printf("%c %d %d
",pipei[i].first,pipei[i].second,fg[i]);
181         /*for (i=1;i<=cnt;i++)
182         {
183             if (fg[i])
184             {
185                 char c=pipei[i].first;
186                 if (c=='.') c=s1[pos];
187                 int tt=0;
188                 while (pos<len1&&s1[pos]==c)
189                 {
190                     pos++;
191                     tt++;
192                     if (tt==pipei[i].second) break;
193                 }
194                 if (tt<pipei[i].second)
195                 {
196                     can=false;
197                     //cout<<pos<<" "<<tt<<" "<<i<<" "<<"hhhhhhh"<<endl;
198                     break;
199                 }
200                 
201             }
202             else
203             {
204                 char c=pipei[i].first;
205                 bool fg2=false;
206                 if (c=='.') 
207                 {
208                     c=s1[pos];
209                     fg2=true;
210                 }
211                 int tt=0;
212                 while (pos<len1&&s1[pos]==c)
213                 {
214                     pos++;
215                     tt++;
216                 }
217                 if (tt<pipei[i].second)
218                 {
219                     //cout<<"hhhhhh"<<endl;
220                     can=false;
221                     //cout<<tt<<" "<<i<<" "<<"hhhhhhhhhh"<<endl;
222                     break;
223                 }
224                 if (i<cnt&&fg2&&pipei[i+1].first==c) 
225                 {
226                     if (fg[i+1])
227                     {
228                         if (tt<pipei[i+1].second)
229                         {
230                             can=false;
231                             break;
232                         }
233                         pos-=pipei[i+1].second;
234                     } else
235                     pos--;
236                 }
237             }
238         }*/
239         //cout<<dp[cnt][0]<<" "<<len1<<endl;
240         puts(can&&dp[cnt][0]<=dp[cnt][1]&&dp[cnt][1]>=len1?"yes":"no");
241     }
242     return 0;
243 }
View Code
原文地址:https://www.cnblogs.com/cxhscst2/p/7442027.html