D1

D1 T1:Clique:
我做的题太少啦,这都没看出来。首先,这个式子是 c[i]−c[j]>=dis(i,j) c[i]-c[j] >= dis(i,j),即在数轴上这样的圆,如果没交点,那么就有边,所以就是最长区间不覆盖。

#include<cstdio>
#include<algorithm>
using namespace std;
const int size = 200005;
struct seg{long long l, r;inline bool operator <(const seg &fu)const{if (fu.r==r) return l < fu.l; return r < fu.r; }
}a[size];long long n;
int main()
{scanf("%lld",&n);for (long long i=1;i<=n;i++){long long tv,tw;scanf("%lld%lld",&tv,&tw);a[i].l = tv-tw;a[i].r = tv + tw;}sort(a+1,a+1+n);long long r = a[1].r;long long ans = 1;for (long long i = 2 ; i <= n ; i++){if (a[i].l >= r)  { ans++; r = a[i].r;}    }    printf("%lld",ans);return 0;
}

D1 T2:Mod
好题啊!!要记下来。
套路题。首先,如果一个区间内最大的数都没有模数大,就不用模啦,因为这是无效的膜。又每次取模后,都只最多剩下以前的一半,所以在这个数不变的情况下,这个数最多有效的被模 logn logn次,这个可以暴力修改。那么每个数被修改 logn logn次,一次改是 logn logn的,总的就是 nlognlogn nlognlogn。

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
const int size = 100005;
struct NODE{ll maxn,cnt;
}t[4*size];
ll n,m;void update1(ll l,ll r,ll qx,ll y,ll node)
{if (l==r){t[node].maxn = y;t[node].cnt = y; //printf("fuck %d %d\n",y,t[l].cnt);return ;}ll mid=(l+r)>>1;if (qx <= mid) update1(l,mid,qx,y,node*2);if (qx >= mid+1) update1(mid+1,r,qx,y,node*2 + 1);    t[node].maxn = max( t[node * 2].maxn , t[node*2+1].maxn ) ;t[node].cnt = t[node*2].cnt + t[node*2+1].cnt ;    //printf("node %d l %d r %d cnt %d maxn %d mid %d\n",node,l,r,t[node].cnt,t[node].maxn,mid);
}void build(ll node,ll l,ll r)
{if (l==r){t[node].cnt=0;t[node].maxn=0;return ;}ll mid = (l+r)>>1;build(node*2,l,mid);build(node*2+1,mid+1,r);
}void update2(ll ql,ll qr,ll l,ll r,ll x,ll node)
{if (r < ql || l > qr) return;if (t[node].maxn < x) return;if (l==r){t[node].cnt%=x;t[node].maxn%=x;return;}ll mid = (l+r)>>1;update2(ql,qr,l,mid,x,2*node);update2(ql,qr,mid+1,r,x,2*node+1);t[node].maxn = max(t[2*node].maxn , t[2*node+1].maxn);t[node].cnt = t[2*node].cnt + t[node*2+1].cnt;
}
ll query(ll l,ll r,ll ql,ll qr,ll node)
{if (r < ql || l > qr) return 0;ll ans = 0;if (ql <= l && r <= qr) return t[node].cnt; ll mid = l+r>>1;ans += query(l,mid,ql,qr,2*node) + query(mid+1,r,ql,qr,2*node+1);return ans;
}
void dfs(ll l,ll r,ll node)
{printf("l is %d r is %d node is %d cnt is %d \n",l,r,node,t[node].cnt);if (l==r) return ;ll mid=l+r>>1;dfs(l,mid,node*2);dfs(mid+1,r,node*2+1);
}
int main()
{//freopen("mod.in","r",stdin);//freopen("modfuck.out","w",stdout);scanf("%lld%lld",&n,&m);ll dod;build(1,1,n);for (ll i=1;i<=n;i++){ll tmp;scanf("%lld",&tmp);update1(1,n,i,tmp,1);}for (ll i=1;i<=m;i++){scanf("%lld",&dod);if (dod==1){ll l,r;scanf("%lld%lld",&l,&r);ll ans = query(1,n,l,r,1);printf("%lld\n",ans);    }elseif (dod==2){ll l,r,x;scanf("%lld%lld%lld",&l,&r,&x);update2(l,r,1,n,x,1);//dfs(1,n,1);}elseif (dod==3){ll k,y;scanf("%lld%lld",&k,&y);update1(1,n,k,y,1);}}return 0;
}

D1 T3:Number
就是你会发现,随着n的变大,那段区间在二进制中有 k k个一的数不会减少。因为从kk到 k+1 k+1时,有 2k 2k在二进制中与 k k的11的个数相同,所以不会减少。那么就可以数位dp一下。令 S(i)=i+1,2,…,2i S(i)={i+1,2,…,2i}, f(i,k) f(i,k)表示 S(i) S(i) 中二进制下恰好有 k k个11的数的个数 (i>0,k≥0) (i>0,k \geq 0 )。设为中有几个数 f(i,k)=Σmin(k,p)x=1Ck−x+1ax+1−Ck−x+1ax f(i,k)=Σ_{x=1} ^ {min⁡(k,p)}C_{a_x+1}^{k−x+1}−C_{a_x}^{k−x+1},其中 p p表示ii在二进制下1的个数, ax a_x表示 i在二进制下第x高的1所在位代表的2的幂次。特判掉 k≤1 k \leq 1 ,那么所有满足条件的 n都在 2∗1018 2*10^{18}以内。 用二分或逐位贪心求出最小和大的 n n即可。

#include <iostream>
#include <cstdio>
#define MAX_DIG 63
using namespace std;
typedef unsigned long long lnt;
int k;    lnt m, c[MAX_DIG+5][MAX_DIG+5], pow[MAX_DIG+5] = {1}, range = 2e18;
void init() {for (int i = 1; i <= MAX_DIG; i++)    pow[i] = pow[i-1]*2;for (int i = 0; i <= MAX_DIG+2; i++)    c[i][0] = 1, c[i][i] = 1;for (int i = 1; i <= MAX_DIG+2; i++)    for (int j = 1; j <= i; j++)    c[i][j] = c[i-1][j-1]+c[i-1][j];
}
lnt f(lnt tmp) {int p = 0;    lnt ret = 0;for (int i = 0; i <= MAX_DIG; i++)    if (tmp&pow[i])    p++;for (int x = 1, cur = MAX_DIG; x <= min(p, k); x++, cur--) {while (!(pow[cur]&tmp))    cur--;ret += c[cur+1][k-x+1]-c[cur][k-x+1];}return ret;
}
lnt fl(lnt l, lnt r) {lnt ret = -1;while (l <= r) {lnt mid = l+r>>1;if (f(mid) <= m)    ret = mid, l = mid+1;else    r = mid-1;}return ret;
}
lnt fu(lnt l, lnt r) {lnt ret = -1;while (l <= r) {lnt mid = l+r>>1;if (f(mid) >= m)    ret = mid, r = mid-1;else l = mid+1;}return ret;
}
int main() {int T; scanf("%d", &T), init();while (T--) {scanf("%llu%d", &m, &k);    if (m == 1 && k == 1) {printf("-1\n");    continue;}if (m == 0) {printf("1 %llu\n", pow[k-1]-1);    continue;}lnt lo =fu(1, range), hi = fl(1, range);printf("%llu %llu\n", lo, hi);}int sdf=0;for (int i=1;i<=10000000;i++) sdf+=0;return 0;
}

D2

D2 T1 :Mine
神奇的定义与转移。设 f(i,j)f(i,j) 表示当前填第 i i个字符为j j的方案数,即j表示当前这个位置还缺几个雷,如果是2就表示这个位置本身就是雷。然后 dp dp就好搞啦。

#include<cstdio>
#include<algorithm>
#include<cstring>using namespace std;
typedef long long ll;
const int size = 1000005;
const ll mod = 1000000007;
char s[size];
int dp[size][10],len;int main(){scanf("%s", s);len = strlen(s);if(len == 1){if(s[0] == '?')printf("2");if(s[0] == '1' || s[0] == '2')printf("0");return 0;}if(s[0] == '0')dp[0][0] = 1;if(s[0] == '1')dp[0][1] = 1;if(s[0] == '2'){printf("0");return 0;}if(s[0] == '*')dp[0][2] = 1;if(s[0] == '?')dp[0][0] = dp[0][1] = dp[0][2] = 1;for(int i = 1;i < len;i ++ ){if(s[i] == '0')  dp[i][0] = dp[i-1][0]; else if(s[i] == '1'){if(i < len-1)dp[i][1] = dp[i-1][0];dp[i][0] = dp[i-1][2];}else if(s[i] == '2')dp[i][1] = dp[i-1][2]; else if(s[i] == '*')dp[i][2] = (dp[i-1][1] + dp[i-1][2]) % mod; else if(s[i] == '?'){if(i < len-1) dp[i][1] = (dp[i-1][0] + dp[i-1][2]) % mod;dp[i][2] = (dp[i-1][1]  +  dp[i-1][2]) % mod;dp[i][0] = (dp[i-1][0]  +  dp[i-1][2]) % mod;}}ll ans = dp[len-1][0] + dp[len-1][2];printf("%lld\n", ans);return 0;
} 

D2 T2:Water
就是水如果能流出去,那么一定有一条路径使得其路径上的值都小于其高度。如果流不出去,那么所有路径上的最大值的最小值要大于其高度(因为一条路径上水只会被最高的挡住,而木桶原理,水只会在最低的被挡住的高度被留住)。所以问题就是从这个块走出矩形的所有路径上的最大值的最小值。相邻块连边,权值为两块的较大值,矩形边界的块向“矩形外”连边,权值为 max(高度,0) max(高度,0),做最小生成树。(最短路也可以)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define inf 1<<30
typedef long long ll;
const ll size = 500;
using namespace std;
struct EDGE{ll to,next,val;inline bool operator < (const EDGE &du )const{return val < du.val;}
}edge[100*size*size];ll cnt=0;
ll n,m,value;
ll mat[size][size] , dis[size*size], head[size*size];
bool in[size*size]; ll SPFA(ll node)
{for (ll i = 0 ; i <= n*m ;i++)dis[i] = inf;queue<ll> q;q.push(node);dis[node]= 0;memset(in,false,sizeof in);in[node] = true;while(!q.empty()){ll h = q.front(); for (ll j=head[h] ; j ;j= edge[j].next){if (dis[edge[j].to ] > max(dis[h],edge[j].val) ){dis[ edge[j].to ] = max(dis[h] , edge[j].val); if (!in[edge[j].to]){q.push(edge[j].to);in[edge[j].to] = 1;}}}    q.pop();in[h] = false;   }
}
ll idx(ll i,ll j)
{return (i*m + j-m);
}
void adde(ll fr,ll to,ll val)
{edge[++cnt]= (EDGE){to,head[fr],val};head[fr] = cnt;
}
void addedge(ll fr,ll to,ll val)
{adde(fr,to,val);adde(to,fr,val);
}
int main()
{//freopen("water.in","r",stdin);//freopen("water.out","w",stdout);scanf("%lld%lld",&n,&m);for (ll i=1;i<=n;i++)for (ll j=1;j<=m;j++)scanf("%lld",&mat[i][j]);for (ll i=1;i<=n;i++)for (ll j=1;j<m;j++){value = max(mat[i][j],mat[i][j+1]);addedge(idx(i,j),idx(i,j+1),value);}for (ll i=1;i<n;i++)for (ll j=1;j<=m;j++){value = max(mat[i][j] , mat[i+1][j]);addedge(idx(i,j),idx(i+1,j),value);}for (ll i=2;i<=n-1;i++){addedge(0 , idx(i,1) , max(mat[i][1] , (ll)0 ) );     addedge(0 , idx(i,m) , max(mat[i][m] , (ll)0 ) );       }for (ll j=1;j<=m;j++)   addedge(0,j,max((ll)0,mat[1][j]));for (ll j=1;j<=m;j++) addedge(0 , idx(n,j) , max((ll)0,mat[n][j]));           SPFA(0);for (ll i=1;i<=n;i++){for (ll j=1;j<=m;j++){if (dis[idx(i,j)] <= mat[i][j]) printf("0 ");else printf("%lld ",dis[idx(i,j)]-mat[i][j]);    //printf("%lld ",dis[idx(i,j)]);}putchar('\n');}//for (ll i=1;i<=m*n;i++)//printf("%d ",dis[i]);return 0;
}

D2 T3:Gcd:
乱反演一下,然后那个桶记因数出现次数。用 f(i) f(i)表示gcd为i的数对个数, g(i) g(i)表示gcd为i的倍数的数对个数。那么 f(i)=Σμ(d)g(d) f(i)=Σμ(d)g(d),我们只需要维护 g(1) g(max(xi)) g(1)~g(max(xi))。记s(i)表示i的倍数的个数,那么 g(i)=s(i)∗(s(i)−1)/2 g(i)=s(i)*(s(i)-1)/2,我们只需要在加入/删除一个数时枚举它的因数修改s即可。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int size = 500005;
bool is_prime[size];
int prime[size],cnt,ud[size];
int s[size] , in[size]  ,a[size];
int n,m,maxn=size;
ll ans=0;void doyoudo()
{memset(is_prime,true,sizeof is_prime);is_prime[1] = 1;ud[1]  = 1;for (int i=2;i<=maxn;i++){if (is_prime[i]) {prime[++cnt]  =  i;ud[i] = -1;}for (int j=1;j<=cnt;j++){int tmp = i*prime[j];if (tmp>maxn) break;is_prime[tmp] = false;if (i %  prime[j]==0){ud[tmp] = 0;break;}elseud[tmp]  =  ud[i]  * (-1);}}
}void add(int x)
{for (int i=1;i*i<=x;i++){if (x%i) continue;ans += ud[i] * (s[i]++);if (i*i!=x)ans += ud[x/i] * (s[x/i]++);}
}void delet(int x)
{for (int i=1;i*i<=x;i++){if (x%i) continue;ans -= ud[i] * (--s[i]);if (i*i!=x)ans -= ud[x/i] * (--s[x/i]);}
}int main()
{scanf("%d%d",&n,&m);for (int i=1;i<=n;i++)scanf("%d",&a[i]);doyoudo();memset(in,0,sizeof in);while (m--){int tmp;scanf("%d",&tmp);if (in[tmp]==1) delet(a[tmp]);else add(a[tmp]);in[tmp]^=1;printf("%lld\n",ans);}//for (int i=1;i<=maxn;i++)//printf("%d %d %d\n",i,is_prime[i],in[i]);
}

D3

D3 T1:string
就是对每种字母单独造棵线段树,然后合并。有点神。

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
int n,m,g[400010],p;
char s[100010];
struct str
{int a[26];inline void clear(){int i;for(i=0;i<26;i++)a[i]=0;}inline str operator+(str x){str p;int i;for(i=0;i<26;i++)p.a[i]=a[i]+x.a[i];return p;}
}f[400010],x;
inline void down(int i,int k)
{if(g[i]!=-1){g[i<<1]=g[i];f[i<<1].clear();f[i<<1].a[g[i]]=k;g[i<<1|1]=g[i];f[i<<1|1].clear();f[i<<1|1].a[g[i]]=k;g[i]=-1;}
}
inline void change(int i,int j,int k,int l,int r,int x)
{if(l<=j && k<=r){f[i].clear();f[i].a[x]=k-j+1;g[i]=x;}else{down(i,k-j+1>>1);if(l<=(j+k>>1))change(i<<1,j,j+k>>1,l,r,x);if(r>(j+k>>1))change(i<<1|1,(j+k>>1)+1,k,l,r,x);f[i]=f[i<<1]+f[i<<1|1];}
}
inline str sum(int i,int j,int k,int l,int r)
{if(l<=j && k<=r)return f[i];else{down(i,k-j+1>>1);str p={};if(l<=(j+k>>1))p=p+sum(i<<1,j,j+k>>1,l,r);if(r>(j+k>>1))p=p+sum(i<<1|1,(j+k>>1)+1,k,l,r);return p;}
}
int main()
{//freopen("string.in","r",stdin);//freopen("string.out","w",stdout);int i,j,k;scanf("%d%d%s",&n,&m,&s);for(p=1;p<n;p<<=1);for(i=1;i<2*p;i++)g[i]=-1;   for(i=1;i<=n;i++)change(1,1,p,i,i,s[i-1]-'a');while(m--){scanf("%d%d%d",&i,&j,&k);x=sum(1,1,p,i,j);if(k)for(k=0;k<26;k++){if(x.a[k])change(1,1,p,i,i+x.a[k]-1,k);i+=x.a[k];}elsefor(k=25;k>=0;k--){if(x.a[k])change(1,1,p,i,i+x.a[k]-1,k);i+=x.a[k];}}for(i=1;i<p;i++)down(i,1);for(i=1;i<=n;i++)printf("%c",'a'+g[p+i-1]);printf("\n");return 0;
}

D3 T2:Matrix
这道题只好意会一下,用 f[i][j] f[i][j]表示做到前 i列,已经有 j列在右侧区间放 1的方案数。 i i越过一个左侧区间的右端点时,从之前剩下空列中选一个在这个左侧区间放 1。也就是说,在扫到i时,我们只在右端点不大于i的左区间放1,转移时分在右侧区间放1或不放 1。还是好转移的。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const ll size = 3003;
const ll mod = 998244353;
ll bucl[size] , bucr[size] , l[size] ,r[size];
ll p[size],inv[size];
ll dp[size][size];
ll n,m;int main()
{scanf("%lld%lld",&n,&m);for (ll i=1;i<=n;i++){scanf("%lld%lld",&l[i],&r[i]);bucl[ l[i] ]++;bucr[ r[i] ]++;}for (ll i=1;i<=m;i++){bucl[i]+=bucl[i-1];bucr[i]+=bucr[i-1];}//for (ll i=1;i<=m;i++)printf("%d ",bucl[i]);//for (ll i=1;i<=m;i++)printf("%d ",bucr[i]);putchar('\n');//inv[1]=1;p[1]=1;//for (ll i=2;i<=n;i++) {p[i]= (p[i-1]*i)%mod; inv[i] = (mod-mod/i)*inv[i%mod];}(dp[0][0]=1)%=mod;for  (ll i=1;i<=m;i++){ dp[i][0] = dp[i-1][0]%mod;for (ll j = 1;j<= i;j++){(dp[i][j] += ( dp[i-1][j-1]* (bucr[i] - j + 1  ) )%mod + dp[i-1][j])%=mod;}for (ll p = bucl[i-1]+1 ; p <= bucl[i] ; p++)for (ll j = 0;j<=i;j++)(dp[i][j] *= (i - p - j +1))%=mod; }/*for (ll i=1;i<=m;i++){for (ll j=0;j<=m;j++)printf("%d ",dp[i][j]);printf("\n");}*/printf("%lld",dp[m][n]);return 0;
}

D3 T3:Big
我们发现,对手是把我们现在得到的数在二进制下把第一位移到最右边(位数限制为nn位的二进制数),又因为我们可以取遍1到 2n−1 2^n-1的数,所以换不换没啥意义,就是要把a序列换一下。问题转化为选一个数,使它左移位后与 m+1 m+1个给定数分别异或的最小值大。然后造字典树,如果当前为0,1都有,则出来只能是0,反之只有一个,则是1。

#include<cstdio>
#include<algorithm>
typedef long long ll;
const ll size = 100005;
int n,m;
int trie[32*size][2] , cnt = 0;
ll ans = 0 , anscnt = 0;
int a[size],b[size];void insert (int x)
{int now = 0;for (int i = n ; i >= 1; i--){int tmp = ( x & ( 1 << ( i - 1 ) ) ) > 0 ? 1 : 0; if (!trie[now][ tmp ] ) trie[now][tmp] = ++cnt;now = trie[now][tmp];}
}int Rieman_Lebel_Change(int x)//黎曼与勒贝尔变换(乱写的)
{return ( ( 2 * x ) / ( 1 << n ) + (2 * x) ) % (1 << n );
}void solve(int dep,int node,ll bigth)
{if (dep <= 0){if (bigth>ans){ans = bigth;anscnt = 1;}else if (bigth==ans) anscnt++;return ;}if (trie[node][1]&&trie[node][0]){solve(dep-1,trie[node][1],bigth);solve(dep-1,trie[node][0],bigth);}elseif (trie[node][1])solve(dep-1,trie[node][1], bigth| ( 1 << (dep-1) ) );elseif (trie[node][0])solve(dep-1,trie[node][0], bigth| ( 1 << (dep-1) ) );}
int main()
{scanf("%d%d",&n,&m);for (int i=1;i<=m;i++){scanf("%d" , &a[i]);a[i] ^= a[i-1];}for (int i = 0;i<=m;i++){int tmp = Rieman_Lebel_Change(a[i]) ^ (a[m] ^ a[i]);insert(tmp);}solve(n,0,0);printf("%lld\n%lld",ans,anscnt);
}

D4

D4 T1:Mayuri
就是约瑟夫问题,可以有 O(min(n,m)) O(min(n,m))或 O(mlogn) O(mlogn)的,又因为m小,所以用第一个好一点。

#include<cstdio>
#include<algorithm>
#include<ctime>
#include<iostream>
using namespace std;
typedef long long ll;
const int size = 10005;
ll dfs2(ll,ll);
ll T,n,m;
ll dfs(ll n)
{if (n==1) return 0;else return    ( dfs( n - 1 )    +  m ) %n;
}
int main()
{ scanf("%lld",&T);    while (T--){scanf("%lld%lld",&n,&m);printf("%lld\n",dfs2(n,m)+1);}    return 0;    }ll dfs2( ll n, ll m ){ ll p = 0;if (m==1) return n-1;       for (ll i=2;i<=n;i++){(p+=m)%=i;    ll x = (i-p) / (m-1) ;if (x+i<n){ i+=x;(p += m*x)%=i;} else{p+=m*(n-i);i=n;}    }               return p%n; }

D4 T2:Kurisu
化简之后变成这个
然后bit就好啦。

#include<cstdio>
#include<algorithm>
#include<ctime>
#include<iostream>
using namespace std;
typedef long long ll;
const int size = 1000005;
const ll mod = 20170927;
ll x[size],y[size];
ll x2[size],y2[size],xy2[size],xy[size];
ll n,m,dod;
ll lowbit(ll x){return (x&(-x));}void update(ll x,ll *c,ll del)
{while (x<=n){(c[x] += del)%mod;x+=lowbit(x);}
}ll query(ll x,ll *c)
{ll ans=0;while (x){(ans+=c[x])%=mod;x-=lowbit(x);}return ans%mod;
}
int main()
{//freopen("kurisu.in","r",stdin);//freopen("kurisu.out","w",stdout);scanf("%lld%lld",&n,&m);for (int i=1;i<=n;i++){scanf("%lld%lld",&x[i],&y[i]);update(i,x2,x[i]*x[i]%mod);update(i,y2,y[i]*y[i]%mod);update(i,xy,x[i]*y[i]%mod);}for (int i=1;i<=m;i++){scanf("%lld",&dod);if (dod==1){ll p,xx,yy;scanf("%lld%lld%lld",&p,&xx,&yy);update(p,x2,xx*xx-x[p]*x[p]);update(p,y2,yy*yy-y[p]*y[p]);update(p,xy,(xx*yy-x[p]*y[p]+mod)%mod);x[p]=xx;y[p]=yy;}elseif (dod==2){ll l,r;scanf("%lld%lld",&l,&r);//printf("%lld%lld\n",l,r);ll sx = (query(r,x2) - query(l-1,x2))%mod;ll sy = (query(r,y2)  -  query(l-1,y2))%mod;ll sxy = (query(r,xy) - query(l-1,xy))%mod;ll ans  = ( (sx*sy%mod  - sxy*sxy%mod)+mod)%mod;(ans +=mod)%=mod;printf("%lld\n",ans);         }    }return 0;
}

D4 T3:Okarin
就是一个最长公共上升子序列。
(无输出方案版)

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll size = 5005;
ll dp[size],a[size],b[size];
ll n,m;
int main()
{scanf("%lld",&n);for (int i=1;i <= n;i++) scanf("%lld",&a[i]);scanf("%lld",&m);for (int i=1;i <= m;i++) scanf("%lld",&b[i]);for (int i=1;i <= n;i++){ll maxn=0;for (int j = 1 ; j <= m ; j++){if (a[i] == b[j]) dp[j] = maxn+1;elseif (a[i] > b[j]) maxn = max(maxn , dp[j]);}}ll ans=0;for (ll i = 1 ; i <= m ; i++)ans = max(ans , dp[i]);printf("%lld",ans);
}

D5

D5 T1:Adore
就是数位dp,0表示这位是偶数,1表示这位是奇数。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int size = 100005 , mod = 998244353 ;
int f[2][2048];
int pre[20],aft[20],cnt[2048] ;//
int m,k;int main()
{scanf("%d%d",&m,&k);int now = 0;for (int i = 1 ; i <= k ; i++){int tmp;scanf("%d",&tmp);now |= tmp << ( i - 1 );}for (int i = 1 ; i <= 2047 ; i++) cnt[i] = cnt[i >> 1 ] ^ (i & 1);int t = 0; f[t][now] = 1 ; int maxn = ( 1 << k ) - 1 ;for (int I = 2 ; I <= m-2 ; I++){memset(pre , 0 , sizeof pre);memset(aft , 0 , sizeof aft);t ^= 1;memset(f[t],0,sizeof f[t]);for (int i = 1 ; i <= k ; i++) for (int j = 1 ; j <= k ; j++){int tmp; scanf("%d",&tmp);pre[j] |=  tmp << ( i - 1 ) ;aft[i] |=  tmp << ( j - 1 ) ;            }for (int i = 0 ; i <= maxn ; i++)if (f[t^1][i]){int s0=0 , s1=0;for (int j = 1 ; j <= k ; j++){s0 |= cnt[pre[j] & i] << (j-1);s1 |= cnt[aft[j] & i] <<(j-1);}( f[t][s0] += f[t^1][i] )%= mod;( f[t][s1] += f[t^1][i] )%= mod;}    }int wtf = 0;   for (int i=1;i<=k;i++){int tmp;scanf("%d",&tmp);wtf |= tmp << ( i - 1 ) ;}int ans = 0;for (int i=0;i<=maxn;i++)if (cnt[i & wtf ] == 0) (ans += f[t][i])%=mod;printf("%d",ans);}

D5 T2:Confess
乱搞,随机选n对就好啦(我绝对不会告诉你,倒着搜就不用随机啦)。证明:证明?我们不妨算一算如果随机选两个集合,他们交的期望 min(Σ2ni=1C(ci,2)C(n+1,2)|Σ2ni=1ci=n(n+1))=n−12 min(Σ^{2n}_{i=1}\frac{C(c_i,2)}{C(n+1,2)}|Σ^{2n}_{i=1} ci = n(n + 1)) =\frac{n-1}{2}注意n 是偶数,所以大于 n−12 \frac{n-1}{2} 即可能会有交为n 的,由于大了一个常数,所以至少有 n n 对!随机O(n)O(n) 对即可。
这是STD,我的是倒着搜的,要遭hack,就不放啦。

#include <iostream>
#include <cstdio>
#include <map>
#include <set>
#include <queue>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <bitset>
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define dep(i,a,b) for(int i = a; i >= b; i--)
#define Rep(i,a) for(int i = 0; i < a; i++)
#define pb(a) push_back(a)
#define mp(a,b) make_pair(a,b)
#define ab(x) ((x) < 0 ? -(x) : (x))
using namespace std;
typedef long long LL;
typedef map<int, int>::iterator mit;
typedef set<int>::iterator sit;
const int N = 6010;
int n;bitset<2 * N> a[N];void init() {scanf("%d",&n); int m = (n * 2 - 1) / 6 + 1;rep(i,1,n + 1) {rep(j,1,m) {char c = getchar(); while (c < 33) c = getchar();c -= 33;Rep(d,6) a[i][(j - 1) * 6 + d] = c >> d & 1;}}
}bool check() {int x = rand() % (n + 1) + 1, y = rand() % n + 1; if (y >= x) y++;if ((int)(a[x] & a[y]).count() >= n / 2) { printf("%d %d\n",x,y); return true; } else return false;
}int main() {freopen("confess.in","r",stdin);freopen("confess.out","w",stdout);srand(233); init();int t = 3 * n; if (t < 100) t = 100;rep(i,1,t) if (check()) return 0;return 0;
}

D5 T3:Repulsed
就是贪心一样的 dp dp,我们只配那些距离为k的房间与灭火器。考虑自底向上贪心。 G[x][k] G[x][k] 表示 x x下面距离为kk的需要灭火器的房间数, F[x][k] F[x][k]表示 x x下面距离为kk 的多余灭火器数,每个灭火器和房间的匹配在 lca lca 处理每次假设子树里已经最优了,那么 G[x][k] G[x][k]一定要用 F[x][0] F[x][0]填满。

#include<cstdio>
#include<algorithm>
using namespace std;
const int size = 100005;
typedef long long ll;
ll n,s,k;
ll ans = 0;
struct EDGE{ll to,next;
}edge[ 2 * size];ll cnt=0;
ll fa[size] , head[size];
ll f[size][30],g[size][30];void adde(ll fr,ll to)
{edge[++cnt]=(EDGE){to,head[fr]};head[fr] = cnt;
}
void addedge(ll fr,ll to)
{adde(fr,to);adde(to,fr);
}ll calc(ll x) {return (x/s + ( ( x % s ) > 0 ) ); }ll dfs1(ll node,ll Fe)
{fa[node] = Fe;for (ll j =head[node];j;j = edge[j].next)if (edge[j].to!= Fe) dfs1(edge[j].to,node);
}ll dfs2(ll node)
{for (ll j=head[node];j;j=edge[j].next){if (edge[j].to!=fa[node]) {dfs2(edge[j].to);for (ll i = 1;i <= k;i++){f[node][i] = min(n , f[node][i] + f[edge[j].to][i-1]);g[node][i] += g[edge[j].to][i-1];}}}g[node][0]++;if (g[node][k]){ll need = calc(g[node][k]);ans += need;f[node][0] = min (need * s , n);}for (ll i=0;i<=k;i++){ll j = min(g[node][i],f[node][k-i]);g[node][i] -= j; f[node][k-i] -= j;}for (ll i=0;i<=k-1;i++){ll j = min(g[node][i],f[node][k-1-i]);g[node][i] -= j; f[node][k-1-i] -= j;}
}
int main()
{scanf("%lld%lld%lld",&n,&s,&k);for (ll i=1;i<n;i++){ll fr,to;scanf("%lld%lld",&fr,&to);addedge(fr,to);}dfs1(1,0);dfs2(1);for (ll i=0;i<=k;i++)for (ll j=0;j<=k;j++){if (i+j<=k){ll need = min(f[1][i],g[1][j]);f[1][i] -= need; g[1][j] -= need;}    }    ll cnt=0;for (ll i=0;i<=k;i++) cnt+=g[1][i];ans += calc(cnt);printf("%lld",ans);
}

D6

D6 T1:starway
好题。你考虑如果现在我们定一个答案,那么我们人就可以变成一个园啦,如果走不动,那么拦住他的就是一条路径,那么每个点再与上下边界连表,就变成了最小生成树。这是完全图,用 prim prim,然后边存不下,就可以先不存,扫的时候在算,然后更新后才加边。这样还不用打标记,造好了图直接跑就可以啦。

//看我程序多美观
//美观啊,太美观了!!!
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#define f(x,y,z) for (int (x) = (y) ; (x) <= (z) ; (x)++)
#define d(x,y,z) for (int (x) = (y) ; (x) >= (z) ; (x)--)
using namespace std;
typedef long long ll;
const ll size = 6010;
int n , m , k ;
struct     EDGE {ll  to , next;ll val;
} edge[2 * size]; ll cnt = 0;ll d[size];
ll head[size] , pre[size] , x[size] , y[size];
bool vis[size];
ll ans = 0 ;void adde(ll fr , ll to , ll val)
{edge[++cnt] = (EDGE){  to , head[fr] , val};head[fr] = cnt;
}
void addedge(ll fr , ll to , ll val)
{adde(fr , to , val );adde(to , fr , val );
}ll dis(ll a , ll b)
{if (a > b) swap(a , b);if (a == k + 1 && b == k + 2) return  1ll * m * m ; else if (b == k + 1) return  1ll * y[a] * y[a] ;else if (b == k + 2) return 1ll * ( m - y[a] ) * ( m - y[a] ) ;else return 1ll * ( x[a] - x[b] ) * ( x[a] - x[b] ) + 1ll * ( y[a] - y[b] ) * ( y[a] - y[b] ) ;
}void dfs(ll node , ll f , ll c)
{//printf("%d %d\n",node,c);if (node == k + 2) { ans = c; return ;}else for (ll j = head[node] ; j ; j = edge[j].next)if ( edge[j].to != f) dfs( edge[j].to , node , max( c , edge[j].val ) );
}int main()
{//freopen("starway.in","r",stdin);//freopen("starway23.out","w",stdout);scanf("%lld %lld %lld" , &n , &m , &k );const ll inf = 1ll * m * m + 10;for (ll i = 1 ; i <= k ; i++) scanf("%lld %lld" , &x[i] , &y[i] );for (ll i = 1 ; i <= k + 2 ; i++) d[i] = inf;d[k + 1] = 0;memset(vis , false , sizeof vis);for (ll t = 1 ; t <= k + 2 ; t++){ll minm = inf ; ll flag = 0;for (ll i = 1 ; i <= k + 2 ; i++) if ( minm > d[i] && !vis[i] ){minm = d[i];flag = i;}if ( pre[flag] )  addedge(pre[flag] , flag , d[flag]);vis[flag] = 1;for (ll i = 1 ;i <= k + 2 ; i++)if ( dis( flag , i ) < d[i] && !vis[i] ){d[i] = dis( flag , i );pre[i] = flag;}}dfs(k + 1 , 0 , 0);printf( "%.9lf\n" , sqrt(ans) / 2 );//for (ll i=1;i<=cnt;i++)//printf("%d %lld\n",edge[i].to,edge[i].val); return 0;
}

D6 T2:knows
其实就是极长上升序列考虑 O(n2) O(n^2) 的 dp dp, fi f_i 表示左边最后一个选的是谁,每次转移的时候枚举一个前面既不相交,又能保证极长的 j j 转移这样的j一定是个上升序列,线段树维护上升序列即可。复杂度为 O(nlog2n) O(nlog^2n)。

#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair <int , int> Node;
const int size = 200050;
const int inf = 2002010910;
int n , p[size] , w[size] , f[size];
Node tr[size * 4] , wtf[size * 4];
#define mp make_pair
#define mid ( ( l + r ) >> 1 )
Node operator + (const Node &a , const Node &b){if (b.first == inf) return a; else return mp( b.first , min(a.second , b.second) );
}  void build(int node , int l , int r)
{tr[node] = wtf[node]  = mp(inf , inf);if (l == r) return ;build(node * 2 , l , mid);build(node * 2 + 1 , mid + 1 , r);
}Node calc (int node , int l , int r , Node x)
{if (l == r)return x > tr[node] ? tr[node] : mp(inf,inf);if (tr[node * 2] < x)return calc(node * 2 , l , mid , x) + wtf[node]; elsereturn calc(node * 2 + 1 , mid + 1 , r , x) ;
}void update(int node,int l,int r)
{wtf[node] = calc(node * 2 + 1 , mid + 1 , r , tr[node*2]);tr[node] = tr[node * 2] + wtf[node];
}void modify(int node,int l,int r,int p,Node x)
{if (l == r){tr[node] = x;return ;}if (p <= mid)modify(node * 2 , l , mid , p , x);elsemodify(node * 2 + 1 , mid + 1 , r , p , x);update(node , l , r);}
void query(int node,int l,int r,int ql,int qr,Node &x)
{    if (l >= ql && r <= qr){x = x+ calc(node , l , r , x);return ;}if (ql <= mid) query(node * 2 , l , mid , ql , qr , x);if (qr >= mid + 1) query(node * 2 + 1 , mid + 1 , r , ql , qr , x);
}
#define trr stf
#define node Node
int main()
{scanf("%d" , &n);build(1, 1, n);for (int i = 1; i <= n; i++)scanf("%d", p + i);for (int i = 1; i <= n; i++)scanf("%d", w + i);for (int i = n; i >= 1; i--) {Node cur = make_pair(inf, inf);query(1, 1, n, p[i], n, cur);f[i] = (cur.first < inf) ? (w[i] + cur.second) : w[i];cur = make_pair(i, f[i]);modify(1, 1, n, p[i], cur);}Node ans = make_pair(inf, inf);query(1 , 1 , n, 1, n, ans);printf("%d", ans.second);return 0;
}

D6 T3:lost
维护凸包,二分弹栈。

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll size = 500006;
ll st[size][22];
ll d[size] , c[size] , fa[size] , ans[size];
ll n;void wei_dfs(ll node)
{if (node == 0) d[node] = 0 ; else d[node] = d[fa[node] ] + 1 ;ll cur = fa[node] ; for (ll i = 21 ;i >= 0 ; i--)//这里数字只要比 log (n)大就可以了 {ll to = st[cur][i];if (to == 0) continue;ll nowzi = c[to] - c[node] , nowfa = d[node] - d[to];ll fazi  = c[ st[to][0] ] - c[node] , fafa  = d[node] - d[ st[to][0] ];if (fafa * nowzi >= fazi * nowfa)  cur = st[to][0];//(c_v - c_cur) / (d_u - d_v) 的 min) 即 (c_v - c_cur) / (d_v - d_u) 的max  算了,要移项变号 麻烦啊 } ll to = cur;ll nowzi = c[to] - c[node] , nowfa = d[node] - d[to];ll fazi  = c[ st[to][0] ] - c[node] , fafa =  d[node] - d[ st[to][0] ];//此处巨坑 注意是与node比较 而不是单调队列优化那样 害我检查了30min if (fafa * nowzi >= fazi * nowfa) cur = st[to][0];        ans[node] = cur ; st[node][0] = cur ;//更新答案 for (ll i = 1 ; i <= 21 ; i++)st[node][i] = st[ st[node][i-1] ][i - 1];
}int main()
{//freopen("lost.in","r",stdin);//freopen("lost2333.out","w",stdout);scanf("%lld",&n);for (ll i = 0 ; i < n ; i++)//我发现好像必须要移这个位 scanf("%lld" , &c[i]);for (ll i = 1 ; i < n ; i++)scanf("%lld" , &fa[i]) , fa[i]--;fa[0] = -1;for (ll i = 1 ; i < n ; i++)wei_dfs(i);for (ll i = 1; i < n; ++i)printf("%.10lf\n", (double) (c[ans[i]] - c[i]) / (d[i] - d[ans[i]]) );
}

D7

D7 T1 :conjucate
期望可加性,考虑每个在第一个数之前被抓的概率,并且与其他元素无关,有独立性,所以有第i堆的贡献是: aiai+a1 \frac{a_i}{a_i + a_1}。

#include<cstdio>
double ans = 1;
long long n,a[100010];
int main()
{scanf("%lld",&n);for (int i = 1;i<=n;i++)scanf("%lld",&a[i]);for (int i=2;i<=n;i++)ans += (double) a[i]/(double)(a[1]+a[i]);printf("%.12lf",ans);
}

D7 T2:conjuct
乱搞dp lcs。

//做不来啦、、、粘的STD
#include <iostream>
#include <cstdio>
#include <map>
#include <set>
#include <queue>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define dep(i,a,b) for(int i = a; i >= b; i--)
#define Rep(i,a) for(int i = 0; i < a; i++)
#define pb(a) push_back(a)
#define mp(a,b) make_pair(a,b)
#define ab(x) ((x) < 0 ? -(x) : (x))
using namespace std;
typedef long long LL;
typedef map<int, int>::iterator mit;
typedef set<int>::iterator sit;
typedef pair<int, int> pii;
#define x first
#define y second
const int N = 5010, inf = 1e6 + 10;
int T, n, f[N][2][2], g[3][N][2][2], a[N];void upd(int &a, int b) { a = (b > a) ? b : a;  }void work() {scanf("%d",&n); int tot = 0, c0 = 0, c1 = 0, c2 = 0; rep(i,1,n) scanf("%d",a + i), tot += (a[i] == 2), c0 += (a[i] == 0), c1 += (a[i] == 1), c2 += (a[i] == 2);if (!c0 || !c1) { printf("0\n"); return; }if (!c2) { printf("-1\n"); return; }rep(i,0,2) rep(j,0,n) Rep(d0,2) Rep(d1,2) g[i][j][d0][d1] = -inf;g[2][0][0][0] = 0;int ans = 0; rep(i,1,n) {rep(j,0,n) Rep(d0,2) Rep(d1,2) f[j][d0][d1] = -inf;Rep(d,3) rep(j,0,i - 1) Rep(d0,2) Rep(d1,2) {int D0 = d0 || (a[i] == 0), D1 = d1 || (a[i] == 1);if (d == 2 && a[i] == 2) D0 = true, D1 = true;if ((a[i] ^ d) == 1 || (a[i] == 2)) f[j + 1][D0][D1] = max(f[j + 1][D0][D1], g[d][j][d0][d1] + 1);else f[j][D0][D1] = max(f[j][D0][D1], g[d][j][d0][d1] + 1);}rep(j,0,i) Rep(d0,2) Rep(d1, 2) g[a[i]][j][d0][d1] = max(g[a[i]][j][d0][d1], f[j][d0][d1]);rep(j,0,tot) ans = max(ans, max(f[j][0][0], f[j][1][1]));rep(j,0,tot - 1) ans = max(ans, max(f[j][0][1], f[j][1][0]));if (a[i] == 2) ans = max(ans, max(f[tot][0][1], f[tot][1][0]));}printf("%d\n",n - ans);
}int main() {scanf("%d",&T);while (T--) work();return 0;
}

D7 T3:conjecture
乱搞。

D8

D8 T1 graph:
贪心,把图建成树,然后每次贪心取,注意到我们应该在这个点的边数为偶数时全取,奇数时向下再取一个。

#include<cstdio>
#include<vector>
using namespace std;
const int maxn = 100050;
struct edge {int to, vis, opp;
};
struct node {int to, real;
};
vector<edge> G[maxn];
vector<node> F[maxn];
int vis[maxn];
int siz[maxn];
int ans[maxn][3], ansn;
int n, m;
int read() {int a = 0, c = 0, w = 1;while(c < '0' || c > '9') {if(c == '-') w = -1; c = getchar();}while(c >= '0' && c <= '9') {a = a * 10 + c - 48; c = getchar();}return a * w;
}int dfs1(int x) {vis[x] = 1;F[x].clear();for(int i = 0; i < G[x].size(); i++) if(!G[x][i].vis) {G[x][i].vis = 1;G[G[x][i].to][G[x][i].opp].vis = 1;if(!vis[G[x][i].to]) {F[x].push_back((node){G[x][i].to, -1});siz[x] += dfs1(G[x][i].to) + 1;}else{F[x].push_back((node){n, G[x][i].to});siz[x] += 1;}}return siz[x];
}
void dfs2(int x, int odd, int fa) {if(odd == 0) {int single = 0, p;for(int i = 0; i < F[x].size(); i++) {int v = F[x][i].to;if(siz[v] % 2 == 0) {single++;if(single == 1) p = (F[x][i].real != -1 ? F[x][i].real : v);else{single = 0;ans[ansn][0] = (F[x][i].real != -1 ? F[x][i].real : v);ans[ansn][1] = x;ans[ansn++][2] = p;}dfs2(v, 0, x);}else dfs2(v, 1, x);}}else{int hungry = 1, single = 0, p;for(int i = 0; i < F[x].size(); i++) {int v = F[x][i].to;if(hungry && siz[v] % 2 == 0) {hungry = 0;ans[ansn][0] = fa;ans[ansn][1] = x;ans[ansn++][2] = (F[x][i].real != -1 ? F[x][i].real : v);dfs2(v, 0, x);}else if(siz[v] % 2 == 0) {single++;if(single == 1) p = (F[x][i].real != -1 ? F[x][i].real : v);else{single = 0;ans[ansn][0] = (F[x][i].real != -1 ? F[x][i].real : v);ans[ansn][1] = x;ans[ansn++][2] = p;}dfs2(v, 0, x);}else dfs2(v, 1, x);}}
}int main() {n = read(); m = read();for(int i = 0; i < m; i++) {int from = read()-1, to = read()-1;G[from].push_back((edge){to, 0, G[to].size()});G[to].push_back((edge){from, 0, G[from].size()-1});}for(int i = 0; i < n; i++) if(!vis[i]) {dfs1(i);dfs2(i, 0, -1);}printf("%d\n", ansn);for(int i = 0; i < ansn; i++) printf("%d %d %d\n", ans[i][0]+1, ans[i][1]+1, ans[i][2]+1);return 0;
}

D8 T2 permutation:
注意到我们先反一下原数列,构造 p[i] p[i]表示i现在在原来的那个数列,所以现在交换就变成了相邻交换。然后有些距离小于 k <script type="math/tex" id="MathJax-Element-87">k</script>的两个的相对位置不会变,所以靠此建图,拓扑排序,dfs一遍就好了。

#include<bits/stdc++.h>
using namespace std;
int a[500010],pos[500010];
bool fl;const int maxn=500010;
int n,k,p[maxn],q[maxn],deg[maxn];
int tote,FIR[maxn],TO[maxn<<1],NEXT[maxn<<1];
priority_queue<int> pq;namespace SegTree{int mn[maxn<<2];
#define lc (nd<<1)
#define rc (nd<<1|1)
#define mid ((s+t)>>1)void init(){memset(mn,0x3f3f3f3f,sizeof(mn));}void update(int nd,int s,int t,int id,int val){if (s==t) {mn[nd]=val; return;}if (id<=mid) update(lc,s,mid,id,val);else update(rc,mid+1,t,id,val);mn[nd]=min(mn[lc],mn[rc]);}int query(int nd,int s,int t,int l,int r){if (l<=s&&t<=r) return mn[nd];int Ans=0x7fffffff;if (l<=mid) Ans=min(Ans,query(lc,s,mid,l,r));if (r> mid) Ans=min(Ans,query(rc,mid+1,t,l,r));return Ans;}
}void addedge(int u,int v)
{TO[++tote]=v;NEXT[tote]=FIR[u];FIR[u]=tote;deg[v]++;
}
void read(int &x)
{char c=getchar(); x=0;while (c<'0'||c>'9') c=getchar();while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
}
int main()
{//freopen("permutation.in","r",stdin);//freopen("permutation.out","w",stdout);scanf("%d",&n);scanf("%d",&k);if (n<=10000){for(int i=1;i<=n;++i)scanf("%d",&a[i]),pos[a[i]]=i;if(k==1){for(int i=1;i<=n;++i)printf("%d\n",i);return 0;}fl=1;while(fl){fl=0;for(int i=1;i<=n;++i){for(int j=a[i]-1;j>0;--j){if(pos[j]<i||pos[j]-i<k)break;if(!fl)fl=1;swap(pos[a[i]],pos[j]);swap(a[pos[a[i]]],a[pos[j]]);}    }}for(int i=1;i<=n;++i)printf("%d\n",a[i]);}else{int i,x;for (i=1;i<=n;i++)read(p[i]),q[p[i]]=i;SegTree::init();for (i=n;i>=1;i--){x=SegTree::query(1,1,n,q[i]-k+1,q[i]);if (x<=n) addedge(q[x],q[i]);x=SegTree::query(1,1,n,q[i],q[i]+k-1);if (x<=n) addedge(q[x],q[i]);SegTree::update(1,1,n,q[i],i);}for (i=1;i<=n;i++)if (!deg[i]) pq.push(i);for (i=n;i>=1;i--){int u=p[i]=pq.top(); pq.pop();for (int p=FIR[u];p;p=NEXT[p])if (!(--deg[TO[p]])) pq.push(TO[p]);}for (i=1;i<=n;i++) q[p[i]]=i;for (i=1;i<=n;i++) printf("%d\n",q[i]);}
}

D8 T3 tree:
每条边都至少出现了一次,所以最优的情况就是所有边权之和,然后能不能取到证不来,反正可以,所以加起来就好啦。(注意爆longlong)

#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
typedef long long ll;
ll n,k;
ll ans=0;
int main()
{scanf("%lld",&n);ll fr,to,val;for (int i=1;i<n;i++)scanf("%lld%lld%lld",&fr,&to,&val) ,ans+=val;printf("%lld",ans);return 0;
}

总结:

这次去雅礼,总的考的不好,也许是因为是高一不稳定的原因。所以回来后要好好提升自己的知识水平,下次去AK雅礼集训。

2017国庆 雅礼集训 题解合集相关推荐

  1. 数据结构二之线段树Ⅱ——KiKi‘s K-Number,ball,The Child and Sequence,「雅礼集训 2017 Day1」市场,Atlantis

    值域线段树+势能线段树+扫描线 KiKi's K-Number ball The Child and Sequence 「雅礼集训 2017 Day1」市场 Atlantis KiKi's K-Num ...

  2. [LOJ 6042]「雅礼集训 2017 Day7」跳蚤王国的宰相(树的重心+贪心)

    [LOJ 6042]「雅礼集训 2017 Day7」跳蚤王国的宰相 description solution 一个到所有节点距离和最小的节点 ⇔\Leftrightarrow⇔ 树的重心(满足最重的儿 ...

  3. #6029. 「雅礼集训 2017 Day1」市场(势能,区间除)

    #6029. 「雅礼集训 2017 Day1」市场 用线段树维护数列,区间上维护最大最小值,区间和还有标记,修改时,区间加直接做,而区间除时,递归到线段树上某一区间,如果这一操作等价于区间加(也就是最 ...

  4. #6034. 「雅礼集训 2017 Day2」线段游戏 李超树

    #6034. 「雅礼集训 2017 Day2」线段游戏 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统 ...

  5. loj #6046. 「雅礼集训 2017 Day8」爷

    #6046. 「雅礼集训 2017 Day8」爷 题目描述 如果你对山口丁和 G&P 没有兴趣,可以无视题目背景,因为你估计看不懂 -- 在第 63 回战车道全国高中生大赛中,军神西住美穗带领 ...

  6. LibreOJ 6514. 「雅礼集训 2018 Day10」文明【虚树+LCA】

    6514. 「雅礼集训 2018 Day10」文明 [题目描述] 传送门 [题解] 考虑笨蛋的写法,可以用LCA求出1号和其他点的中点,然后DFS搜索Size大小即可,但是,复杂度显然要炸,但是我们会 ...

  7. 雅礼集训2017day1 矩阵

    雅礼集训2017day1 矩阵 题目大意 给你一个 n × n n\times n n×n的 01 01 01矩阵,每次操作将一行转置后赋值到一列.如果能让矩阵全为 1 1 1,则输出最小操作次数:否 ...

  8. 雅礼集训及WC2018划水记

    雅礼集训1.30~2.3 noip考成250,没得去thuwc和pkuwc,和czy等去参加本来只有samjia和栋栋的集训队模拟.抱着被虐的心态去比赛. 第一天刚到比较困,比赛有点没精神,看到t3的 ...

  9. Loj #6503. 「雅礼集训 2018 Day4」Magic

    Loj #6503. 「雅礼集训 2018 Day4」Magic 题目描述 前进!前进!不择手段地前进!--托马斯 · 维德 魔法纪元元年. 1453 年 5 月 3 日 16 时,高维碎片接触地球. ...

最新文章

  1. [YTU]_2617(B C++时间类的运算符重载)
  2. 蓝桥杯-8-1因式分解(java)
  3. linux搜索文件为1kb,Linux常用命令
  4. spring-session + redis 实现集群 session 共享
  5. Infinite Tree
  6. Eviews 9.0新版本新功能——预测(Auto-ARIMA预测、VAR预测)
  7. MCU串行通讯和并行通讯的区别以及UART的理解
  8. T3137 栈练习1 codevs
  9. mysql 修改密码
  10. svn删除文件或目录后提交失败及解决
  11. SqlServer利用ODBC连接Mysql数据库
  12. python自动登录百度_python模拟百度登陆
  13. 用命令打开文件服务器资源管理器,Windows10使用命令参数打开文件资源管理器的方法...
  14. str中的join方法,fromkeys(),set集合,深浅拷贝(重点)
  15. windows下安装虚拟机
  16. JS的组成-JS数组方法-JS函数-系统化学习
  17. 关于c语言学习的建议
  18. 2021江苏连云港高考成绩查询时间,2021年江苏连云港高考时间:6月7日至9日
  19. java选中多张图片上传
  20. 中间件漏洞(Apache篇)

热门文章

  1. 28BYJ-48步进电机
  2. 2021.07.28
  3. 删除数组中的指定元素——C++实现
  4. 〖2023·新星计划·第四季〗开启,Python赛道火爆预热中~ 欢迎小伙伴们报名~
  5. 【编译原理复习】第六章---- 属性文法和语法制导翻译
  6. css 多行文字左对齐,纯CSS实现文字一行居中,多行左对齐的方法
  7. Qt的长期支持版本的知识搜集
  8. 【开关电源四】电源拓扑之Cuk、Sepic、Zeta
  9. 知识图谱学习(一)(笔记整理)
  10. 安装 Visual Studio Community 2015