• 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
  • 相关阅读:
    python发送邮件
    nginx的信号量和平滑升级
    CentOS6下nginx的源码安装
    mysql备份与还原之mysqldump
    myslq基本语法(3)
    mysql基本语法(2)
    MySQL中数据表和数据的操作
    mysql概述及基本语法(1)
    shell的随机数
    浏览器的跨域问题的解决办法
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/7442027.html
Copyright © 2020-2023  润新知