训练合集-Mind the Gap

训练合集-Mind the Gap

Member :EdGrass afeng111 xishuiw

wirtten by xishuiw

目录

2023暑期训练前半

0.2022-2023 ACM-ICPC Latin American Regional Programming Contest

赛时过题 DEILM

补题ACH

D.Daily Trips

签到 问什么时候需要带伞

#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN =  3e5+7;
const ll mod = 1e9+7;
const ll inf = 0x3f3f3f3f;
void solve(){
	int n,a,b;cin>>n>>a>>b;
	for(int i=1;i<=n;i++){
		char ch1,ch2;
		cin>>ch1>>ch2;
		if(ch1=='Y'||b==0){
			cout<<"Y ";
			a--;
			b++;
		}
		else {
			cout<<"N ";
		}
		if(ch2=='Y'||a==0){
			cout<<"Y ";
			b--;
			a++;
		}
		else {
			cout<<"N ";
		}
		cout<<"\n";
	} 
}
signed main(){
	close;
	solve();
}

E.Empty Square

#include <iostream>
using namespace std;

const int N = 1007;
int vis[N];

int main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, k, e;
    cin >> n >> k >> e;
    vis[k] = 1;
    int l = e, r = n - k - e;
    int ans = 0;
    if (l > r)
        swap(l, r);
    if (l == 1)
    {
        if (vis[1])
            ans++;
        else
            vis[1] = 1;
    }
    else if (l == 2)
    {
        if (vis[2])
        {
            vis[1] = 1;
            ans++;
        }
        else
            vis[2] = 1;
    }
    else if (l == 3)
    {
        if (vis[3])
        {
            vis[1] = vis[2] = 1;
        }
        else
        {
            vis[3] = 1;
        }
    }
    else if (l == 4)
    {
        if (vis[4] == 1)
        {
            vis[1] = 1;
            vis[3] = 1;
        }
        else
        {
            vis[4] = 1;
        }
    }

    if (r == 1)
    {
        if (vis[1])
            ans++;
    }
    else if (r == 2)
    {
        if (vis[2])
        {
            if (vis[1])
                ans += 2;
            else
                ans++;
        }
    }
    else if (r == 3)
    {
        if (vis[3])
        {
            if (vis[2])
            {
                if (vis[1])
                {
                    ans += 3;
                }
                else
                    ans += 2;
            }
            else
            {
                if (vis[1])
                {
                    ans += 1;
                }
            }
        }
    }
    else if (r == 4)
    {
        if (vis[4] == 1)
        {
            if (vis[3])
            {
                if (vis[2])
                {
                    if (vis[1])
                        ans += 4;
                    else
                        ans += 3;
                }
                else
                {
                    if (vis[1])
                        ans += 2;
                    else
                        ans++;
                }
            }
            else
            {
                if (vis[1])
                    ans++;
            }
        }
    }
    cout << ans << endl;
}

I. Italian Calzone & Pasta Corner

找一个最大上升子序列 路径里 图很小 对每个点跑bfs 注意剪枝

#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN =  3e5+7;
const ll mod = 1e9+7;
const ll inf = 0x3f3f3f3f;
int mp[300][300];
int vis[300][300],f[300][300];
int fx[4][2]={1,0,-1,0,0,1,0,-1};
void solve(){
	int n,m;cin>>n>>m;
	 for(int i=1;i<=n;i++){
	 	for(int j=1;j<=m;j++) cin>>mp[i][j];
	 }
	 int ans=0;
	 for(int i=1;i<=n;i++){
	 	for(int j=1;j<=m;j++){
	 		int res=0;
	 		if(vis[i][j]) continue;
	 		for(int x=1;x<=n;x++){
	 			for(int y=1;y<=m;y++) f[x][y]=0;
			 }
			 queue<array<int,2>> que;
			 que.push({i,j});
			 f[i][j]=1;
			 vis[i][j]=1;
			 res=1;
			 while(que.size()){
			 	int x=que.front()[0],y=que.front()[1];
			 	que.pop();
			 	for(int v=0;v<4;v++){
			 		int xx=x+fx[v][0],yy=y+fx[v][1];
			 		if(xx<1||xx>n||yy<1||yy>m||f[xx][yy]||mp[x][y]>mp[xx][yy]) continue;
			 		f[xx][yy]=1;res++; 
			 		vis[xx][yy]=1;
			 		que.push({xx,yy});
				 }
			 	
			 }
			 ans=max(ans,res);
		 }
	 }
	 cout<<ans<<"\n";
}
signed main(){
    close;
	solve();
}

L. Lazy Printing

给打印机 找长度在限制范围内的最小的模板串数量

贪心地不停向后枚举 然后用hash优化下过了 但是这个还是n2的 数据太弱 标准做法kmp

#include <bits/stdc++.h>

#define close                         \
	std::ios::sync_with_stdio(false); \
	cin.tie(0);                       \
	cout.tie(0)
using namespace std;
typedef unsigned long long ULL;

const int N = 1007;
const int MANX = 4e5+7;
int n, d,P=131;
char s[200010];
const int inf = 2e9;
ULL h[MANX], p[MANX];
ULL get(int l, int r) {
	return h[r] - h[l - 1] * p[r - l + 1];
}
inline int find(int now, int i) {
//	int pos = now;
	int t = 0;
	int ans=now;
	int pos=now;
	pos+=i;
	ULL k=get(now,pos);
	while(pos<=n){
		ULL tmp=get(pos-i,pos);
		if(tmp!=k) break;
		ans=pos;
		pos+=i;
	}
	pos=now;
	while (s[pos] == s[ans]) {
		++pos;
		++ans;
		++t;
		if (t == i) {
			t = 0;
			pos = now;
		}
	}
	return ans;
}
int main() {
	close;
	p[0] = 1;
	cin >> s+1 >> d;
	n = strlen(s+1);
	for (int i = 1; i <= n; i ++ ) {
		h[i] = h[i - 1] * P + s[i];
		p[i] = p[i - 1] * P;
	}

	int now = 1;
	int ans = 0;
	while (now <= n) {
		int mx = 0;
		for (int i = 1; i <= d; ++i) {
			int k = find(now, i);
			if (k > mx) {
				mx = k;
			}
		}
		++ans;
		now = mx;
	}
	cout << ans;
}

M. Maze in Bolt

可以旋转的锁 一步一步转看看能不能下去 并且可以换头的方向

队友搓的搜索 很牛

#include <iostream>
#include <queue>
using namespace std;

const int N = 1007;
char mp[N][N];
int row, col;
int flag[N][N];
int vis[N][N];
char tag[N];
int bg = -1;
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};

bool check(int r, int c)
{
    for (int i = 0; i < col; i++)
    {
        if (tag[(bg + i) % col] == '0')
            continue;
        if (mp[r][(c + i) % col] == '1')
            return false;
    }
    return true;
}

bool bfs()
{
    for (int i = 1; i <= row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            if (check(i, j))
                flag[i][j] = 1;
            else
                flag[i][j] = 0;
            vis[i][j] = 0;
            // if (flag[i][j])
            //     cout << i << ' ' << j + 1 << endl;
        }
    }
    queue<pair<int, int>> q;
    bool getans = false;
    for (int i = 0; i < col; i++)
    {
        if (flag[1][i])
        {
            vis[1][i] = 1;
            q.push({1, i});
        }
    }
    while (q.size())
    {
        int x = q.front().first, y = q.front().second;
        q.pop();
        if (x == row)
        {
            getans = true;
            break;
        }
        for (int i = 0; i < 4; i++)
        {
            int xx = x + dx[i];
            int yy = (y + dy[i] + col) % col;
            if (xx <= 0 || xx > row)
                continue;
            if (vis[xx][yy])
                continue;
            if (flag[xx][yy] == 0)
                continue;
            vis[xx][yy] = 1;
            q.push({xx, yy});
        }
    }
    return getans;
}

int main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> row >> col;
    for (int i = 0; i < col; i++)
    {
        cin >> tag[i];
        // cout << tag[i];
        if (tag[i] == '1' && bg == -1)
            bg = i;
    }
    // cout << endl;
    // cout << bg << endl;
    for (int i = 1; i <= row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            cin >> mp[i][j];
        }
    }
    if (bg == -1)
    {
        cout << "Y";
        return 0;
    }
    if (bfs())
        cout << "Y";
    else
    {
        for (int i = 0; i < col - i - 1; i++)
        {
            // cout << i << ' ' << col - i << endl;
            swap(tag[i], tag[col - i - 1]);
        }
        for (int i = 0; i < col; i++)
        {
            // cout << tag[i];
            if (tag[i] == '1')
            {
                bg = i;
                break;
            }
        }
        // cout << endl;
        if (bfs())
            cout << "Y";
        else
            cout << "N" << endl;
    }
}

A. Asking for Money

每个人被一个人要钱时候可以对两个人要钱

随机某个人被要1元 问谁最后有可能不亏钱

不亏钱条件是有一个点能同时到达三个点

建反图 三个点同时到达一个点 复杂度大大优化

#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN =  3e5+7;
const ll mod = 1e9+7;
const ll inf = 0x3f3f3f3f;
vector<int> adj[MAXN];
pair<int,int> e[MAXN];
int vis[MAXN],tmp[MAXN];
void solve(){
	int n;cin>>n;
	for(int i=1;i<=n;i++){
		int u,v;cin>>u>>v;
		adj[u].push_back(i);
		adj[v].push_back(i);
		e[i]={u,v};
	}
	for(int i=1;i<=n;i++){
		for(int it=1;it<=n;it++) vis[it]=0,tmp[it]=0;
		queue<int>que;
		que.push(i);
		vis[i]=1;
		while(que.size()){
			int x=que.front();
			que.pop();
			for(auto &v:adj[x]){
				if(!vis[v]){
					vis[v]=1;
					que.push(v);
				}
			}
		}
		for(int j=1;j<=n;j++) if(vis[j]) tmp[j]++;
		//
		for(int it=1;it<=n;it++) vis[it]=0;
		que.push(e[i].first);
		vis[e[i].first]=1;
		while(que.size()){
			int x=que.front();
			que.pop();
			for(auto &v:adj[x]){
			    if(v==i) continue;
				if(!vis[v]){
					vis[v]=1;
					que.push(v);
				}
			}
		}
		for(int j=1;j<=n;j++) if(vis[j]) tmp[j]++;
		//
		for(int it=1;it<=n;it++) vis[it]=0;
		que.push(e[i].second);
		vis[e[i].second]=1;
		while(que.size()){
			int x=que.front();
			que.pop();
			for(auto &v:adj[x]){
			    if(v==i) continue;
				if(!vis[v]){
					vis[v]=1;
					que.push(v);
				}
			}
		}
		for(int j=1;j<=n;j++) if(vis[j]) tmp[j]++;
		int flag=0;
		for(int j=1;j<=n;j++){
			if(tmp[j]==3) flag=1;
		}
		if(flag) cout<<"Y";
		else cout<<"N";
	}
}
signed main(){
	solve();
}

C. City Folding

码力太弱 推不出公式

#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN =  3e5+7;
const ll mod = 1e9+7;
const ll inf = 0x3f3f3f3f;
#define int ll
int f[MAXN];
vector<int> ans;
void solve(){
	int n,p,h;cin>>n>>p>>h;
	p--;h--;
	for(int i=n-1;i>=0;i--){
		if(h>=(1LL<<i)) {
			f[n-i-1]=1;
			h=(1LL<<(i+1))-1-h;
		}
	//cout<<"# h = "<<h<<" "<<f[n-i-1]<<"\n";
	} 
	//预处理是否需要翻动来增加高度,f为1表示需要增加一次高度
	//3 8 3 第一次翻动增加4 不需要 第二次翻动增加2 需要,翻动后长度变为剩下的长度 
	for(int i=n-1;i>=0;i--){
		//第i次翻动 h改变的是1<<(n-i-1) p改变的是1<<i 
		if(!f[i]){ 
	//	cout<<f[i];//需要增加h 
			if(p<(1LL<<i)){
				cout<<"R"; 
			}
			else{
				cout<<"L";
				p-=(1LL<<i);
			}
		}
		else{//需要的长度大 
	//	cout<<f[i];
		//反转后高度会改变 
			if(p<(1LL<<i)){
				cout<<"L";
				p=(1LL<<i)-1-p; 
			}
			else{
				cout<<"R";
				p=(1LL<<(i+1))-1-p;
			}
		}
	} 
}
signed main(){
	solve();
}

1.The 2022 ICPC Asia Nanjing Regional Contest

赛时过题AGIM 补题D

A. Stop, Yesterday Please No More

有很多袋鼠 满的 然后会根据题目给的走 问有几种放洞的方法 可以让最后剩下k个袋鼠

我一开始在走洞 写了一个自己样例都过不去的做法

队友上机敲了一发走袋鼠的 直接过了

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <string>
#include <stack>
#include <iomanip>
// 小数位    cout<<fixed<<setprecision(12)<<dis[n+1]<<endl;
using namespace std;
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)

const int N = 1e3 + 7;
typedef long long ll;

int row, col, lv;
string s;
ll vis[N][N];

ll count(int x1, int y1, int x2, int y2)
{
    // cout << vis[x2][y2] << " " << vis[x1 - 1][y1 - 1] << ' ' << vis[x1 - 1][y2] << ' ' << vis[x2][y1 - 1] << endl;
    return vis[x2][y2] + vis[x1 - 1][y1 - 1] - vis[x1 - 1][y2] - vis[x2][y1 - 1];
}

void solve()
{
    cin >> row >> col >> lv;
    for (int i = 1; i <= row; i++)
        for (int j = 1; j <= col; j++)
            vis[i][j] = 0;
    cin >> s;
    ll v = 0, h = 0; // 竖直,水平
    ll mxv0, mxv1, mxh0, mxh1;
    mxv0 = mxv1 = mxh0 = mxh1 = 0;
    ll x = 1, y = 1;
    for (int i = 0; i < s.length(); i++)
    {
        if (s[i] == 'U')
        {
            v++;
            x = max(x, v + 1);
            mxv0 = max(mxv0, v);
        }
        else if (s[i] == 'D')
        {
            v--;
            mxv1 = min(mxv1, v);
        }
        else if (s[i] == 'L')
        {
            h--;
            y = max(y, -h + 1);
            mxh1 = min(mxh1, h);
        }
        else
        {
            h++;
            mxh0 = max(mxh0, h);
        }
    }

    ll szrow = row - mxv0 + mxv1, szcol = col - mxh0 + mxh1;
    if (szrow <= 0 || szcol <= 0)
    {
        if (lv == 0)
            cout << row * col << endl;
        else
            cout << 0 << endl;
        return;
    }

    // cout << szrow << ' ' << szcol << endl;
    // cout << x << ' ' << y << endl;
    vis[x][y] = 1;
    for (int i = 0; i < s.length(); i++)
    {
        if (s[i] == 'U')
        {
            x--;
        }
        else if (s[i] == 'D')
        {
            x++;
        }
        else if (s[i] == 'L')
        {
            y--;
        }
        else
        {
            y++;
        }
        vis[x][y] = 1;
    }
    for (int i = 1; i <= row; i++)
    {
        for (int j = 1; j <= col; j++)
        {
            vis[i][j] += -vis[i - 1][j - 1] + vis[i - 1][j] + vis[i][j - 1];
        }
    }
    // for (int i = 1; i <= row; i++)
    // {
    //     for (int j = 1; j <= col; j++)
    //     {
    // cout << vis[i][j] << ' ';
    // }
    // cout << endl;
    // }
    ll ans = 0;
    // cout << count(2, 2, 3, 3) << endl;
    ll sz = szrow * szcol;

    // for (int i = szrow; i <= row; i++)
    // {
    //     for (int j = szcol; j <= col; j++)
    //     {
    //         ll cnt = count(i - szrow + 1, j - szcol + 1, i, j);
    //         if (cnt + lv == sz)
    //             ans++;
    //     }
    // }
    // cout << ans << ' ';
    // ans = 0;
    for (int i = 1; i <= row; i++)
    {
        for (int j = 1; j <= col; j++)
        {
            ll cnt = count(max(1ll, i - szrow + 1), max(1ll, j - szcol + 1), i, j);
            if (cnt + lv == sz)
                ans++;
        }
    }
    cout << ans << endl;
}

int main()
{
    close;
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
}

G. Inscryption

野兽合并 写太急了被我wa了一发

显然是合并越多越好 0可以变成1 所以是类似反悔贪心

0多了就把1个0变1

#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
#define int ll
const ll MAXN =  1e6+7;
const ll mod = 1e9+7;
const ll inf = 0x3f3f3f3f;
int a[MAXN];
void solve(){
	int n;cin>>n;
	int cnt0=0,cnt1=0,cnt2=0;
	int now=0;
	int flag=1;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		if(a[i]==0) cnt0++;
		else if(a[i]==1) cnt1++;
		else cnt2++;
		if(a[i]!=0)
		now+=a[i];
		else now-=1;
		if(now<0){
			if(cnt0){
				cnt0--;
				cnt1++;
				now+=2;
			}
			else flag=0;
		}
	}

	int fz=1+cnt1,fm=1+cnt1-cnt0-cnt2;
	if(!flag) cout<<"-1\n";
	else{
		int tmp=__gcd(fz,fm);
		cout<<fz/tmp<<" "<<fm/tmp<<"\n"; 
	}
}
signed main(){
	close; 
	int t;cin>>t;
	while(t--) 
	solve();
}

I. Perfect Palindrome

结论:全变成一样的

#include<bits/stdc++.h>
#define ll long long
#define PII pair<int,int>
//  #define int long long
using namespace std;
constexpr ll mod=1e9+7; 
const ll inf=0x3f3f3f3f;  
const ll INF=0x3f3f3f3f3f3f3f3f;  
const double eps=1e-10;  
const int N=2e5+10;
// struct node{
//     friend bool operator<(const node&a,const node&b){
//         return ;
//     }
// }
//priority_queue<ll,vector<ll>,greater<ll>>pq;
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;}
inline void write(int x){char F[200];int tmp=x>0?x:-x;if(x<0) putchar('-');int cnt=0;while(tmp>0){F[cnt++]=tmp%10+'0';tmp/=10;}while(cnt>0)putchar(F[--cnt]);}
inline int combination(int n,int k){int sum=0;if (n==k||k==0){return 1;}else{return combination(n-1,k)+combination(n-1,k-1);}}
map<char,int>mp;
void solve(){
    // int n=read();
    string s;
    mp.clear();
    cin>>s;
    for(int i=0;i<s.size();i++){
        mp[s[i]]++;
    }
    int maxx=-1;
    for(auto it:mp){
        int y=it.second;
        maxx=max(y,maxx);
    }
    cout<<s.size()-maxx<<'\n';
    //puts(ans>0?"YES":"NO");
    //puts(ans>0?"Yes":"No");
}

signed main(){
    // ios::sync_with_stdio(false);
    // cin.tie(0);
    // cout.tie(0);
    // int t=1;
   int t=read();
    while(t--){
        solve();
    }
}

M. Drain the Water Tank

队友写的 向量判上边和下边 因为给定顺序排过了 所以就看看是不是下凹和下平

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <string>
#include <stack>
#include <iomanip>
// 小数位    cout<<fixed<<setprecision(12)<<dis[n+1]<<endl;
using namespace std;
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)

const int N = 2e5 + 7;
const int inf = 2e9;

struct node
{
    int x, y;
} nd[N];

int n;

void solve()
{
    cin >> n;
    int mn = inf, index = 0;
    for (int i = 0; i < n; i++)
        cin >> nd[i].x >> nd[i].y;

    int ans = 0;
    for (int i = 0; i < n; i++)
    {
        int x = nd[i].x, y = nd[i].y;
        int nx = (i + 1) % n;
        int xx = nd[nx].x, yy = nd[nx].y;
        int nxx = (nx + 1) % n;
        int xxx = nd[nxx].x, yyy = nd[nxx].y;

        if (x < xx && y > yy)
        {
            if (yyy > yy && (xxx >= xx || (yyy - yy) * (x - xx) < (y - yy) * (xxx - xx)))
                ans++;
        }
        else if (x == xx && y > yy)
        {
            if (yyy > yy && xxx > xx)
                ans++;
        }
        else if (x > xx && y > yy)
        {
            if (yyy > yy && xxx > xx && (yyy - yy) * (x - xx) < (y - yy) * (xxx - xx))
                ans++;
        }
    }
    // cout << ans << endl;
    for (int i = 0; i < n; i++)
    {
        int nx = (i + 1) % n;
        while (nd[i].y == nd[nx].y && nd[i].x < nd[nx].x)
            nx = (nx + 1) % n;
        if (nx == (i + 1) % n)
            continue;
        int pre = (n + i - 1) % n;
        if (nd[pre].y > nd[i].y && nd[(n + nx - 1) % n].y < nd[nx].y)
            ans++;
    }
    cout << ans << endl;
}

int main()
{
    close;
    int t = 1;
    // cin >> t;
    while (t--)
    {
        solve();
    }
}

D. Chat Program

一次可以加一个等差数列 问第k大的数最多是多大

二分答案 看看加上后>=mid的数是否大于k个

#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN =  3e5+7;
const ll mod = 1e9+7;
const ll inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
#define int ll
int n,k,m,c,d;
int a[MAXN],pre[MAXN];
bool check(int mid){
	int cnt=0;
	for(int i=1;i<=n;i++) pre[i]=0;
	for(int i=1;i<=n;i++){
		if(a[i]>=mid) cnt++;
		else{
			int tmp=mid-a[i];
			tmp-=c;
			int pos;
			if(tmp<=0) {
				pos=max(i-m+1,1LL);
				pre[pos]++;
				pre[i+1]--;
			}
			else{
				int p;
				if(d==0){
					continue;
				}
				p=tmp/d;
				if(p*d!=tmp) p++;
				if(p>m) continue;
				pos=i-p;
				if(pos<1) continue;
				p=max(i-m+1,1LL);
				pre[p]++;
				pre[min(pos+1,i+1)]--; 
			} 
		}
	}
	pre[1]+=cnt;
	for(int i=1;i<=n;i++){
		pre[i]=pre[i]+pre[i-1];
		if(pre[i]>=k) return true;
	}
	return false;
}
void solve(){
	cin>>n>>k>>m>>c>>d;
	for(int i=1;i<=n;i++) cin>>a[i];
	int l=0,r=INF;
	while(l<=r){
		int mid=l+r>>1;
		if(check(mid)){
			l=mid+1;
		}
		else{
			r=mid-1;
		}
	} 
	cout<<r;
}
signed main(){
	close;
	solve();
}

2.2019-2020 ICPC Asia Hong Kong Regional Contest

赛时过题BDG 补题EJ

B. Binary Tree

每次拿不改变奇偶性 算树的总大小就行了

#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN =  3e5+7;
const ll mod = 1e9+7;
const ll inf = 0x3f3f3f3f;
void solve(){
	int n;cin>>n;
	for(int i=1;i<n;i++){
		int u,v;cin>>u>>v;
	}
	if(n%2==1) cout<<"Alice\n";
	else cout<<"Bob\n";
}
signed main(){
	close;
	int t;cin>>t;
	while(t--)
	solve();
}

D. Defining Labels

类似进制转换 队友写的

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const int N = 2e5 + 2;
const ll mod = 200907;
using namespace std;

int k, x;

void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    cin >> k >> x;
    int d = 9 - (10 - k) + 1;
    // cout << d << endl;
    vector<int> ans;
    while (x > 0)
    {
        ans.push_back((x - 1) % d + (10 - k));
        // cout << (x - 1) % d + (10 - k);
        // x = (x - 1) / d + 1;
        x = (x / d) - (int)(x % d == 0);
    }
    for (int i = ans.size() - 1; i >= 0; i--)
        cout << ans[i];
    cout << endl;
}

int main()
{
    close;
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

G. Game Design

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const int N = 2e5 + 2;
const ll mod = 200907;
using namespace std;

int k, cnt;
map<int, int> wei, fa;

void dfs(int k, int f)
{
    cnt++;
    // cout << cnt << ' ' << f << endl;
    fa[cnt] = f;
    int tp = cnt;

    if (k == 1)
    {
        wei[tp] = 1;
        wei[f] += wei[tp];
        return;
    }
    k--;
    if (k % 2 == 0)
    {
        // cout << cnt << endl;
        dfs(2, tp);
        dfs(k / 2, tp);
    }
    else
    {
        dfs(k, cnt);
    }
    wei[f] += wei[tp];
}

void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    cin >> k;
    if (k == 1)
    {
        cout << 2 << endl;
        cout << 1 << endl;
        cout << 1 << ' ' << 2 << endl;
        return;
    }
    // cout << k << endl;
    dfs(k, 0);
    cout << cnt << endl;
    for (int i = 2; i <= cnt; i++)
        cout << fa[i] << ' ';
    cout << endl;
    for (int i = 1; i <= cnt; i++)
        cout << wei[i] << ' ';
    cout << endl;
}

int main()
{
    close;
    int t = 1;
    // cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

E. Erasing Number

能处于中位数的肯定能删

三个连续大数能变成两个的 对于每个数 数连续的大数n2去做

J. Junior Mathematician

数位dp 模板题 赛场看出来了不会写

#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN =  1e4+7;
const ll mod = 1e9+7;
const ll inf = 0x3f3f3f3f;
ll dp[MAXN][62][62];//pos pre 贡献
// dp[i][j][m]
//轮流枚举每一位的情况 都可以由上一位推出 复杂度为O(10n)
//pre表示前缀和 来算此时数的大小
//第三维记录f[x]-x
//f[x] 增加了 pre*x,  x增加了x*1-^n
//贡献=贡献-x*10^n+pre*x
int p[MAXN],upper[MAXN],m;
void init(int x) {
	p[1]=1;
	for(int i=2; i<=x+1; i++) {
		p[i]=p[i-1]*10;
		p[i]%=m;
	}
}
ll dfs(int pos,int pre_num,int c,int flag) {
	int max_number;
	if(pos<=0) return c==0;
	if(!flag&&dp[pos][pre_num][c]!=-1) return dp[pos][pre_num][c];
	if(flag) max_number=upper[pos];
	else max_number=9;
	ll ret=0;
	for(int i=0; i<=max_number; i++) {
//转移方程

		ret+=dfs(pos-1,(i+pre_num)%m,((c-i*p[pos]+pre_num*i)%m+m)%m,flag&&(i==max_number));
		ret=(ret+mod)%mod;
	}
	ret=(ret+mod)%mod;
	if(!flag) dp[pos][pre_num][c]=ret;
	return ret;
}

void solve() {
	string a,b;
	cin>>a>>b>>m;
	int l=max(a.length(),b.length());
	init(l);
	int len=a.length();
	a[len-1]--;
	for(int i=0; i<=l+4; i++) {
		for(int j=0; j<=m; j++) {
			for(int x=0; x<=m; x++) {
				dp[i][j][x]=-1;
			}
		}
	}
	for(int i=len-1; i>=0; i--) {
		if(a[i]>='0'&&a[i]<='9') break;
		a[i]='9',a[i-1]--;
	}
	for(int i=0; i<len; i++) {
		upper[len-i]=a[i]-'0';
	}
	//cout<<"## "<<a<<"\n";
	ll aa=dfs(len,0,0,1);
	for(int i=0; i<=l+4; i++) {
		for(int j=0; j<=m; j++) {
			for(int x=0; x<=m; x++) {
				dp[i][j][x]=-1;
			}
		}
	}
	len=b.length();
	for(int i=0; i<len; i++) {
		upper[len-i]=b[i]-'0';
	}
	ll bb=dfs(len,0,0,1);
	cout<<(bb-aa+mod)%mod<<"\n";
}
signed main() {
	close;
	int t;cin>>t;
	while(t--) 
	solve();
}

3.The 2021 ICPC Asia Nanjing Regional Contest (XXII Open Cup, Grand Prix of Nanjing)

赛时过题ACHM 补题EJ

A. Oops, It’s Yesterday Twice More

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const int N = 2e5 + 2;
const ll mod = 200907;
using namespace std;

int n, a, b;

void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    cin >> n >> a >> b;
    if (a <= n / 2)
    {
        if (b <= n / 2)
        {
            for (int i = 1; i < n; i++)
                cout << "UL";
            for (int i = 1; i < b; i++)
                cout << 'R';
            for (int i = 1; i < a; i++)
                cout << 'D';
        }
        else
        {
            for (int i = 1; i < n; i++)
                cout << "UR";
            for (int i = 1; i < a; i++)
                cout << 'D';
            for (int i = 1; i <= n - b; i++)
                cout << 'L';
        }
    }
    else
    {
        if (b <= n / 2)
        {
            for (int i = 1; i < n; i++)
                cout << "DL";
            for (int i = 1; i < b; i++)
                cout << 'R';
            for (int i = 1; i <= n - a; i++)
                cout << 'U';
        }
        else
        {
            for (int i = 1; i < n; i++)
                cout << "DR";
            for (int i = 1; i <= n - a; i++)
                cout << 'U';
            for (int i = 1; i <= n - b; i++)
                cout << 'L';
        }
    }
}

int main()
{
    close;
    int t = 1;
    // cin>>t;
    while (t--)
    {
        solve();
    }
    return 0;
}

C. Klee in Solitary Confinement

对区间+k 找众数最多的情况

由于数的总数不多,因此考虑dp它+或者不+的状态 实时更新最大值

用map会t 于是对每个数+2e6变成数组

#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN =  1e7+7;
const ll mod = 1e9+7;
const ll inf = 0x3f3f3f3f;
int mp[MAXN],tmp[MAXN],mx[MAXN]; 
int a[MAXN];
void solve(){
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		a[i]+=2e6; 
		mp[a[i]]++;
		tmp[a[i]+m]++;
		tmp[a[i]]--;
		if(tmp[a[i]]<0)
		tmp[a[i]]=0;
		mx[a[i]]=max(tmp[a[i]],mx[a[i]]);
		mx[a[i]+m]=max(tmp[a[i]+m],mx[a[i]+m]);
	} 
	int ans=0;
	for(int i=1;i<=n;i++){
		ans=max(ans,mp[a[i]]+mx[a[i]]);
	}
	cout<<ans;
}
signed main(){
	close;
	solve();
}

H. Crystalfly

树dp

在对u点进行dp的时候 有两种情况

第一种是所有v都删除 留个最大的 dp值由v的所有节点推出

第二种是留一个 但是这个节点的子节点贡献不保留 再由下面推出 然后再加上一个t=3的节点 然后再算v的子节点

取最大值就行 没写明白wa了好久

#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN =  4e5+7;
const ll mod = 1e9+7;
const ll inf = 0x3f3f3f3f;
#define int ll
int a[MAXN],b[MAXN];
vector<int> adj[MAXN];
int dp[MAXN],sum[MAXN];
void dfs(int u,int fa) {
	dp[u]=a[u];
	int tmp=0;
	int max_1=0;
	int max_2=0;
	for(auto v:adj[u]) {
		if(v==fa) continue;
		sum[u]+=a[v];
		dfs(v,u);
		tmp=max(tmp,a[v]);
		if(b[v]==3) {
			if(a[v]>a[max_1]) {
				max_2=max_1;
				max_1=v;
			} else if(a[v]>a[max_2]) {
				max_2=v;
			}
		}
		dp[u]+=dp[v];
		dp[u]-=a[v];
	}
	int temp=dp[u];
	for(auto &v:adj[u]){
		if(v==fa) continue;
		int k=a[v];
		for(auto &it:adj[v]){
			if(it==u) continue;
			k+=dp[it]-a[it];
		}
		if(v==max_1)
		dp[u]=max({temp+tmp,temp-dp[v]+a[v]+k+a[max_2],dp[u]});
		else dp[u]=max({temp+tmp,temp-dp[v]+a[v]+k+a[max_1],dp[u]});
	}
	dp[u]=max(dp[u],temp+tmp);
}
void solve() {
	int n;
	cin>>n;
	for(int i=1; i<=n; i++) cin>>a[i];
	for(int i=1; i<=n; i++) {
		cin>>b[i];
		if(b[i]==2) b[i]=1;
		adj[i].clear();
		dp[i]=0;
		sum[i]=0;
	}
	for(int i=1; i<n; i++) {
		int u,v;
		cin>>u>>v;
		adj[u].push_back(v);
		adj[v].push_back(u);
	}
	sum[0]=inf;
	dfs(1,0);
	cout<<dp[1]<<'\n';
}
signed main() {
	close;
	int t;
	cin>>t;
	while(t--)
		solve();
}

M. Windblume Festival

手玩一下发现结论 至少有一个改变符号 然后最多有n-1个改变符号 特判n=1的情况即可

改变符号贪心

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const int N = 2e6 + 7;
const ll mod = 200907;
using namespace std;

ll n, a[N], ans, sum;

void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    cin >> n;
    ans = sum = 0;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    if (n == 1)
    {
        cout << a[1] << endl;
        return;
    }
    sort(a + 1, a + 1 + n);
    for (int i = 1; i <= n; i++)
    {
        if (i == 1)
            sum -= a[i];
        else if (i == n)
            sum += a[i];
        else
        {
            if (a[i] < 0)
                sum -= a[i];
            else
                sum += a[i];
        }
    }
    cout << sum << endl;
}

int main()
{
    close;
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

E. Paimon Segment Tree

历史和是一种线性的递推 可以由上一个递推过来 由此想到矩阵处理 因此用线段树维护矩阵 加val之后相当于乘矩阵 把求历史和过程中要用的全用矩阵维护好先

有点卡常 少取模!!尽量优化下矩阵 乘法只做一半之类的

#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN =  5e4+7;
const ll mod = 1e9+7;
const ll inf = 0x3f3f3f3f;
const ll M = 4;
inline ll read() { //快读
	ll x=0,f=0;
	char ch=getchar();
	while(ch>'9'||ch<'0') {
		f|=(ch=='-');
		ch=getchar();
	}
	while(ch<='9'&&ch>='0') {
		x=(x<<1LL)+(x<<3LL)+
		  (ch^48);
		ch=getchar();
	}
	return f?-x:x;
}
struct matrix {
	ll x[M+1][M+1];
	matrix() {
		memset(x,0,sizeof(x));
	}
	ll* operator [] (int i) {
		return x[i];
	}
	matrix operator * (matrix b) const {
		matrix res;
		for(int i = 1; i <= M; i ++) {
			for(int j = 1; j <= M; j ++) {
				for(int k = i; k <= j; k ++) {
					res[i][j] += (( x[i][k] *b[k][j]) );
					res[i][j]%=mod;
				}
			}
		}
		return res;
	}
	matrix operator + ( matrix b) const {
		matrix res;
		for (int i = 1; i <=M; i ++) {
			for (int j = i; j <= M; j ++) {
				res[i][j] = (x[i][j] + b[i][j] );
				res[i][j]%=mod;
			}
		}
		return res;
	}
	bool operator != (matrix b) {
		for (int i = 1; i <= M; i ++) {
			for (int j = 1; j <=M; j ++) {
				if (x[i][j] != b[i][j])return true;
			}
		}
		return false;
	}
	void init() {
		for(int i = 1 ; i <=M ; i ++) {
			for(int j = i ; j <=M ; j ++) {
				x[i][j] = (i == j ? 1LL : 0LL);
			}
		}
	}
};
matrix mpow(matrix a,ll m) { //矩阵a的m次方
	matrix res;
	res.init();
	while(m>0) {
		if(m&1) res=res*a;
		a=a*a;
		m>>=1;
	}
	return res;
}
bool check(matrix a) {
	int flag=true;
	for(int i=1; i<=M; i++) {
		for(int j=1; j<=M; j++) {
			if(i!=j&&a.x[i][j]!=0) flag=false;
			else if(i==j&&a.x[i][j]!=1) flag=false;
		}
	}
	return flag;
}
struct Info {
	matrix sum;
};
Info operator +(const Info &a,const Info &b) {
	Info c;
	c.sum=a.sum+b.sum;
	return c;
}
matrix A;
ll a[MAXN];
struct node {
	matrix lazy;
	Info val;
} seg[MAXN<<2];
void up(int id) {
	seg[id].val=seg[id<<1].val+seg[id<<1|1].val;
}
void settag(int id,int l,int r,matrix tag) {
	matrix tmp;
	seg[id].val.sum=seg[id].val.sum*tag;
	seg[id].lazy=seg[id].lazy*tag;
}
void down(int id,int l,int r) {
	if(seg[id].lazy.x[3][4]==0) return;
	int mid=l+r>>1;
	settag(id<<1,l,mid,seg[id].lazy);
	settag(id<<1|1,mid+1,r,seg[id].lazy);
	seg[id].lazy.init();
}
void build(int id,int l,int r) {
	seg[id].lazy.init();
	if(l==r) {
		seg[id].val.sum[1][1]=1;
		seg[id].val.sum[1][2]=a[l];
		seg[id].val.sum[1][3]=a[l]*a[l]%mod;
		seg[id].val.sum[1][4]=a[l]*a[l]%mod;
		return;
	}
	int mid = l+r>>1;
	build(id<<1,l,mid);
	build(id<<1|1,mid+1,r);
	up(id);
}
void modify(int id,int l,int r,int ql,int qr,matrix val) {
	if (ql==l&&r==qr) {
		settag(id,l,r,val);
		return;
	}
	down(id,l,r);
	int mid =(l+r) >> 1;
	if (qr<=mid)
		modify(id <<1,l,mid,ql,qr,val);
	else if (ql>mid)
		modify(id<<1|1, mid+1,r,ql,qr,val);
	else {
		modify(id<<1,l,mid,ql,mid,val);
		modify(id<<1|1,mid+1,r,mid+1,qr,val);
	}
	up(id);
}
Info query(int id,int l ,int r,int ql,int qr) {
	if(ql==l&&r==qr) {
		return seg[id].val;
	}
	down(id,l,r);
	int mid=l+r>>1;
	if(qr<=mid) return query(id<<1,l,mid,ql,qr);
	else if(ql>mid) return query(id<<1|1,mid+1,r,ql,qr);
	else return query(id<<1,l,mid,ql,mid)+query(id<<1|1,mid+1,r,mid+1,qr);
}
vector<array<int,3> > P;
vector<array<int,4> >  Q[MAXN];//id l r ty
ll ans[MAXN];
void solve() {
	int n,m,q;
//	cin>>n>>m>>q;
	n=read();
	m=read();
	q=read();
	for(int i=1; i<=n; i++) a[i]=read();
	build(1,1,n);
	P.push_back({0,0,0});
	for(int i=1; i<=m; i++) {
		int l,r,x;
//		cin>>l>>r>>x;
		l=read();
		r=read();
		x=read();
		P.push_back({l,r,x});
	}
	for(int i=1; i<=q; i++) {
		int l,r,x,y;
	//	cin>>l>>r>>x>>y;
		l=read();
		r=read();
		x=read();
		y=read();
		if(x!=0)
			Q[x-1].push_back({i,l,r,-1});
		Q[y].push_back({i,l,r,1});
	}
	for(auto it:Q[0]) {
		int id=it[0],l=it[1],r=it[2],ty=it[3];
		matrix tmp = query(1,1,n,l,r).sum;
		ans[id]+=ty*tmp[1][4];
	}
	for(int i=1; i<=m; i++) {
		int l=P[i][0],r=P[i][1],x=P[i][2];
		matrix tmp;
		tmp[1][1]=1;
		tmp[1][2]=x;
		tmp[1][3]=1LL*x*x%mod;
		tmp[1][4]=1LL*x*x%mod;
		tmp[2][2]=1;
		tmp[2][3]=2LL*x;
		tmp[2][4]=2LL*x;
		tmp[3][3]=1;
		tmp[3][4]=1;
		tmp[4][4]=1;
		modify(1,1,n,l,r,tmp);
		tmp.init();
		tmp[3][4]=1;
		if(l>1) {
			modify(1,1,n,1,l-1,tmp);
		}
		if(r<n) {
			modify(1,1,n,r+1,n,tmp);
		}
		for(auto it:Q[i]) {
			int id=it[0],l=it[1],r=it[2],ty=it[3];
			matrix tmp = query(1,1,n,l,r).sum;
			ans[id]+=ty*tmp[1][4];
		}
	}
	for(int i=1; i<=q; i++) {
		printf("%lld\n",(ans[i]%mod+mod)%mod);
	//	cout<<(ans[i]%mod+mod)%mod<<"\n";
	}
}
signed main() {
//	close;
	solve();
}

J. Xingqiu’s Joke

找因子用的很暴力 不会证明复杂度的办法

4.2020-2021 ACM-ICPC, Asia Nanjing Regional Contest (XXI Open Cup, Grand Prix of Nanjing)

赛时过题EKL 补题AFHM

E. Evil Coordinate

重新排列路径 然后让路径不会经过某个点

顺时针方向绕着走好像就行了 赛时不小心 写挂了好久

#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN =  3e5+7;
const ll mod = 1e9+7;
const ll inf = 0x3f3f3f3f;
#define int ll
int fx[4][2]= {1,0,0,1,-1,0,0,-1}; //右 上 左 下
int f[4];
string str[4]= {"R","U","L","D"};
void solve() {
	int x,y;
	cin>>x>>y;
	string s;
	cin>>s;
	string ans;
	for(int i=0; i<4; i++) f[i]=0;
	for(auto ch :s) {
		if(ch=='R') f[0]++;
		else if(ch=='U') f[1]++;
		else if(ch=='L') f[2]++;
		else f[3]++;
	}
	int xx=f[0]-f[2];
	int yy=f[1]-f[3];
	if((xx==x&&yy==y)||(x==0&&y==0)) {
		cout<<"Impossible\n";
		return;
	}
	int px=0,py=0;
	int flag1=1,flag2=1,flag3=1,flag4=1;
	for(int i=0;i<4;i++){
		for(int j=1;j<=f[i];j++){
			px+=fx[i][0];
			py+=fx[i][1];
			if(px==x&&py==y) flag1=0;
		}
	}
	
	px=0;
	py=0;
	for(int i=0;i<4;i++){
		int p=(i+1)%4; 
		for(int j=1;j<=f[p];j++){
			px+=fx[p][0];
			py+=fx[p][1];
			if(px==x&&py==y) flag2=0;
		}
	}
	px=0;
	py=0;
	for(int i=0;i<4;i++){
		int p=(i+2)%4; 
		for(int j=1;j<=f[p];j++){
			px+=fx[p][0];
			py+=fx[p][1];
			if(px==x&&py==y) flag3=0;
		}
	}
    px=0;
	py=0;
	for(int i=0;i<4;i++){
		int p=(i+3)%4; 
		for(int j=1;j<=f[p];j++){
			px+=fx[p][0];
			py+=fx[p][1];
			if(px==x&&py==y) flag4=0;
		}
	}
    // cout<<flag1<<" "<<flag2<<" "<<flag3<<" "<<flag4<<'\n';
	if(flag1){
		for(int i=0;i<4;i++){
			for(int j=1;j<=f[i];j++){
				cout<<str[i]; 
			}
		}
	}
	else if(flag2){
		for(int i=0;i<4;i++){
			int p=(i+1)%4;
			for(int j=1;j<=f[p];j++){
				cout<<str[p]; 
			}
		}
	}
	else if(flag3){
		for(int i=0;i<4;i++){
			int p=(i+2)%4;
			for(int j=1;j<=f[p];j++){
				cout<<str[p]; 
			}
		}
	} 
	else if(flag4){
		for(int i=0;i<4;i++){
			int p=(i+3)%4;
			for(int j=1;j<=f[p];j++){
				cout<<str[p]; 
			}
		}
	}
	else{
		cout<<"Impossible";
	}
	cout<<'\n';
}
signed main() {
	int t;
	cin>>t;
	while(t--)
		solve();
}

K. K Co-prime Permutation

显然 当i位置上是i+1时 gcd必为1 否则为i时 gcd为i 推一下就行

#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN =  3e5+7;
const ll mod = 1e9+7;
const ll inf = 0x3f3f3f3f;
void solve(){
	int n,k;cin>>n>>k;
	if(k==0){
		cout<<"-1";
	} 
	else{
		k--;
		for(int i=1;i<=k;i++){
			cout<<i+1<<" ";
		}
		cout<<"1 ";
		for(int i=k+2;i<=n;i++){
			cout<<i<<" ";
		}
	}
}
signed main(){
	close;
	solve();
}

L. Let’s Play Curling

没记错就是找两个蓝色石头中间最大红色数量

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const int inf = 2e9;
const int N = 2e6 + 7;
const ll mod = 200907;
using namespace std;

int n, m;
vector<int> all, a, b;

void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    cin >> n >> m;
    all.clear(), a.clear(), b.clear();
    for (int i = 1; i <= n; i++)
    {
        int tp;
        cin >> tp;
        // cout << tp << ' ';
        a.push_back(tp);
        all.push_back(tp);
    }
    // cout << endl;
    for (int i = 1; i <= m; i++)
    {
        int tp;
        cin >> tp;
        b.push_back(tp);
        all.push_back(tp);
    }
    sort(a.begin(), a.end());
    sort(b.begin(), b.end());
    sort(all.begin(), all.end());
    all.erase(unique(all.begin(), all.end()), all.end());
    // for (int i = 0; i < all.size(); i++)
    // cout << all[i] << ' ';
    // cout << endl;
    for (int i = 0; i < a.size(); i++)
    {
        int tp = a[i];
        a[i] = lower_bound(all.begin(), all.end(), tp) - all.begin() + 1;
        // cout << a[i] << endl;
    }
    // cout << endl;
    for (int i = 0; i < b.size(); i++)
        b[i] = lower_bound(all.begin(), all.end(), b[i]) - all.begin() + 1;
    // cout << endl;
    int mx = 0;
    for (int i = 0; i < b.size() - 1; i++)
    {
        int l = upper_bound(a.begin(), a.end(), b[i]) - a.begin() + 1;
        int r = lower_bound(a.begin(), a.end(), b[i + 1]) - a.begin() + 1;
        // cout << l << ' ' << r << endl;
        mx = max(mx, r - l);
    }
    int l = upper_bound(a.begin(), a.end(), b[m - 1]) - a.begin() + 1;
    int r = lower_bound(a.begin(), a.end(), inf) - a.begin() + 1;
    mx = max(mx, r - l);
    l = 1;
    r = lower_bound(a.begin(), a.end(), b[0]) - a.begin() + 1;
    mx = max(mx, r - l);
    if (mx == 0)
        cout << "Impossible" << endl;
    else
        cout << mx << endl;
}

int main()
{
    close;
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

A. Ah, It’s Yesterday Once More

额场上写差不多了 但是有一个孤立点没找到 寄了 就是斜着走

F. Fireworks

先推出期望计算公式 然后三分答案 场上三分太丑 挂了

#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN =  3e5+7;
const ll mod = 1e9+7;
const ll inf = 0x3f3f3f3f;
#define double long double
double f(int x,int n,int m,double p){
	return ((double)x*n+m)/(1.0-(pow(1-p,x)));
}
void solve(){
	int n,m;
	double p;
	cin>>n>>m>>p;
	p/=10000.0;
	int l=0,r=inf;
	while(l<r){
		int mid1=l+(r-l)/3;
		int mid2=r-(r-l)/3;
		if(f(mid1,n,m,p)<f(mid2,n,m,p)) r=mid2-1;
		else l=mid1+1;
	}
	printf("%.8Lf\n",f(l,n,m,p));
}
signed main(){
	int t;cin>>t;
	while(t--)
	solve();
}

H. Harmonious Rectangle

小范围打表

M. Monster Hunter

感觉类似树上背包 枚举父亲贡献的节点与我与我邻居贡献的

#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN =  3e3+7;
const ll mod = 1e9+7;
const ll inf = 0x3f3f3f3f;
#define int ll
int dp[MAXN][MAXN][2],a[MAXN];// i为顶点的子树 已经用了j个 此时用/不用  减少的最大贡献
vector<int> adj[MAXN];
int n;
int ans=0;
int sum[MAXN];
int sz[MAXN];
void dfs_sum(int u,int fa) {
	sum[u]=a[u];
	sz[u]=1;
	for(auto &v:adj[u]) {
		sum[u]+=a[v];
		dfs_sum(v,u);
	}
	ans+=sum[u];
}
void dfs(int u,int fa) {
	dp[u][1][1]=sum[u];
	for(auto &v:adj[u]) {
		dfs(v,u);
		for(int i=sz[u]; i>=0; i--) { //枚举父节点删了几个 
			for(int j=sz[v];j>=0;j--){
				if(j>0)
				dp[u][j+i][0]=max(dp[u][j+i][0],dp[u][i][0]+max(dp[v][j][0],dp[v][j][1]+a[v]));
				else 
				dp[u][j+i][0]=max(dp[u][j+i][0],dp[u][i][0]+dp[v][j][0]);
				if(j>0&&i>0)
				dp[u][j+i][1]=max(dp[u][j+i][1],dp[u][i][1]+max(dp[v][j][0],dp[v][j][1]));
				else if(i>0)
				dp[u][j+i][1]=max(dp[u][j+i][1],dp[u][i][1]+dp[v][j][0]);
			}
		}
		sz[u]+=sz[v]; 
	}

//	cout<<"delet : u "<<u<<"\n";
//	for(int i=0;i<=n;i++) cout<<"i = "<<i<<" "<<dp[u][i][0]<<" "<<dp[u][i][1]<<"\n";
}
void solve() {
	cin>>n;
	for(int i=1; i<=n; i++) {
		adj[i].clear();
		sum[i]=0;
		for(int j=0; j<=n; j++) dp[i][j][0]=dp[i][j][1]=0;
	}
	ans=0;
	for(int i=2; i<=n; i++) {
		int u;
		cin>>u;
		adj[u].push_back(i);
	}
	for(int i=1; i<=n; i++) cin>>a[i];
	dfs_sum(1,0);
	dfs(1,0);
	for(int i=0; i<=n; i++) {
		cout<<ans-max(dp[1][i][0],dp[1][i][1])<<" ";
	}
	cout<<"\n";
}
signed main() {
	int t;
	cin>>t;
	while(t--)
		solve();
}

5.2022 ICPC Southeastern Europe Regional Contest

赛时过题 AFGHN

A. AppendAppendAppend

一个一个遍历 然后指针二分找下一个的位置 超了+1

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const int N = 2e5 + 7;
const ll mod = 200907;
using namespace std;

string s, t;
vector<int> pos[40];

void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    cin >> s >> t;
    for (int i = 0; i < s.length(); i++)
        pos[s[i] - 'a'].push_back(i);
    int ans = 0, now = 0;
    for (int i = 0; i < t.length(); i++)
    {
        int j = t[i] - 'a';
        int nx = lower_bound(pos[j].begin(), pos[j].end(), now) - pos[j].begin();
        // cout << i << ' ' << now << ' ' << t[i] << ' ' << nx << endl;
        if (nx < pos[j].size())
            now = pos[j][nx] + 1;
        else
            now = 0, i--, ans++;
    }
    cout << ans + 1;
}

int main()
{
    close;
    int t = 1;
    // cin>>t;
    while (t--)
    {
        solve();
    }
    return 0;
}

F. Fortune over Sportsmanship

模拟一下怎么交换 正解应该是dp 不过可能差不多

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const int N = 2e3 + 7;
const ll mod = 200907;
using namespace std;

int n;
ll a[N][N];
vector<pair<int, int>> v;

void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    cin >> n;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            cin >> a[i][j];
    ll ans = 0;
    for (int i = n; i > 1; i--)
    {
        ll mx = 0, idx = 0;
        for (int j = 1; j < i; j++)
            if (mx <= a[j][i])
                mx = a[j][i], idx = j;
        ans += mx;
        // cout << idx << ' ' << i << endl;
        v.push_back({idx, i});
        for (int j = 1; j < idx; j++)
        {
            a[j][idx] = max(a[j][idx], a[j][i]);
        }
        for (int j = idx + 1; j <= n; j++)
        {
            a[idx][j] = max(a[idx][j], a[j][i]);
        }
        // for (int j = 1; j <= n; j++)
        // {
        //     for (int k = 1; k <= n; k++)
        //         cout << a[j][k] << ' ';
        //     cout << endl;
        // }
        // cout << endl;
    }
    cout << ans << endl;
    for (auto i : v)
    {
        cout << i.first << ' ' << i.second << endl;
    }
}

int main()
{
    close;
    int t = 1;
    // cin>>t;
    while (t--)
    {
        solve();
    }
    return 0;
}

G. Gears

设第一个齿轮大小为x 后面的均能用x表示 然后二分一下x的大小 看看区间内是否有不满足的 根据实际情况return true或者false

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
	std::ios::sync_with_stdio(false); \
	cin.tie(0);                       \
	cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
#define int ll
const int N = 5e5 + 7;
const ll mod = 200907;
using namespace std;
int n;
int a[N];
int b[N];
int c[N];
int R[N];
int sum=0;
int mins=1e9+7;
int maxs=0;
bool check(int mid) {
	int tmp=0;
	for(int i=1; i<=n; i++) {
		if(i%2==1) {
			tmp+=mid+c[i];
			if(mid+c[i]<mins){
				return true;
			}
			else if(mid+c[i]>maxs){
				return false;
			}
		} else {
			tmp+=c[i]-mid;
			if(c[i]-mid<mins){
				return false;
			}
			else if(c[i]-mid>maxs){
				return true; 
			}
		}
		//	cout<<"# "<<tmp<<'\n';
	}
	if(tmp>=sum) return false;
	else return true;
}
void solve() {
	cin>>n;
	for(int i=1; i<=n; i++) cin>>a[i];
	for(int i=1; i<=n; i++) {
		cin>>R[i];
		sum+=R[i];
		maxs=max(maxs,R[i]);
		mins=min(mins,R[i]);
	}
	for(int i=2; i<=n; i++) {
		b[i]=a[i]-a[i-1];
	}
	for(int i=1; i<=n; i++) {
		if(i==1) c[i]=0;
		else {
			c[i]=b[i]-c[i-1];
		}
	}
	int l=1,r=1e9+7;
	while(l<=r) {
		int mid=l+r>>1;
		if(check(mid)) {
			l=mid+1;
		} else {
			r=mid-1;
		}
	}
//	cout<<l<<" "<<r<<"\n";
	for(int i=1; i<=n; i++) {
		if(i%2==1) {
			cout<<l+c[i];
		} else cout<<c[i]-l;
		cout<<" ";
	}
	//	freopen("data.in.txt","r",stdin);
	//	freopen("data.out.txt","w",stdout);
}

signed main() {
	close;
	int t = 1;
	// cin>>t;
	while (t--) {
		solve();
	}
	return 0;
}

H. Hanoi

汉诺塔 1可以不受限制

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const int N = 2e5 + 7;
const ll mod = 200907;
using namespace std;

int n;
stack<int> st1, st2, st3;
vector<string> ans;

void add(int k)
{
    stack<int> temp;
    while (st3.size() && k > st3.top())
    {
        temp.push(st3.top());
        st3.pop();
        ans.push_back("3 1");
    }
    st3.push(k);
    ans.push_back("2 3");
    while (temp.size())
    {
        st3.push(temp.top());
        temp.pop();
        ans.push_back("1 3");
    }
}

void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    cin >> n;
    for (int i = 1, tp; i <= n; i++)
    {
        cin >> tp;
        st1.push(tp);
    }
    for (int i = n; i > 0; i--)
    {
        int tp = st1.top();
        st1.pop();
        ans.push_back("1 2");
        add(tp);
    }
    cout << ans.size() << endl;
    for (auto i : ans)
        cout << i << endl;
}

int main()
{
    close;
    int t = 1;
    // cin>>t;
    while (t--)
    {
        solve();
    }
    return 0;
}

N. Nusret Gökçe

让每个相邻的值的差不超过k 使用搜索 分别往左往右递减 遇到大的就从那个地方开始搜 遇到小的并且搜过就return 应该是O(n)

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const int N = 2e5 + 7;
const ll mod = 200907;
using namespace std;
#define int ll
int a[N],f[N];
int n,m;
void dfs(int x){
    int l=x,r=x;
    f[x]=max(f[x],a[x]);
    int now=a[x]-m;
    for(int i=r+1;i<=n;i++){
        if(f[i]<=now&&a[i]<=now){
             f[i]=now;
             now-=m;
        }
        else if(f[i]==0){
            dfs(i);
            break;
        }
        else if(f[i]>now) break;
    }
    now=a[x]-m;
    for(int i=l-1;i>=1;i--){
        if(f[i]<=now&&a[i]<=now){
            f[i]=now;
            now-=m;
        }
        else if(f[i]==0){
            dfs(i);
            break;
        }
        else if(f[i]>now) break;
    }
}
void solve()
{
    cin>>n>>m;
    int maxp=0;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        if(a[i]>a[maxp]) maxp=i;
    }
    f[maxp]=a[maxp];
    dfs(maxp);
    for(int i=1;i<=n;i++){
        cout<<f[i]<<" ";
    }
}

signed main()
{
    close;
    int t = 1;
    // cin>>t;
    while (t--)
    {
        solve();
    }
    return 0;
}

6.The 15th Chinese Northeast Collegiate Programming Contest

赛时过题CEIKM 补题ACDHJ

C. Vertex Deletion

树dp 队友推了很牛的式子 然后dp

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
#define int ll
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int N = 2e5 + 7;
const int MAXN = 2e5 + 7;
const ll mod = 998244353;
using namespace std;
vector<int> adj[MAXN];
int dp[MAXN][3],sz[MAXN];
void dfs(int u,int fa){
	dp[u][0]=1;
	dp[u][1]=1;
	dp[u][2]=1;
	for(auto &v:adj[u]){
		if(v==fa) continue;
		dfs(v,u);
		dp[u][2]*=dp[v][0];
		dp[u][2]%=mod;
	}
	for(auto &v:adj[u]){
		if(v==fa) continue;
		dp[u][0]*=(dp[v][0]+dp[v][1]);
		dp[u][0]%=mod;
	}
	for(auto &v:adj[u]){
		if(v==fa) continue;
		dp[u][1]*=(dp[v][0]+dp[v][1]+dp[v][2]);
		dp[u][1]%=mod;
	}
	dp[u][1]-=dp[u][2];
	dp[u][1]%=mod;
	dp[u][1]=(dp[u][1]+mod)%mod;
//	cout<<"# u : "<<u<<"\n";
//	cout<<dp[u][0]<<" "<<dp[u][1]<<' '<<dp[u][2]<<'\n';
}
void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    int n;
    cin>>n;
    for(int i=1;i<=n;i++) adj[i].clear();
    for(int i=1;i<n;i++){
    	int u,v;cin>>u>>v;
    	adj[u].push_back(v);
    	adj[v].push_back(u);
	}
	dfs(1,0);
	cout<<(dp[1][0]+dp[1][1])%mod<<"\n";
}

signed main()
{
    close;
    int t = 1;
     cin>>t;
    while (t--)
    {
        solve();
    }
    return 0;
}

E. Easy Math Problem

观察了一下发现要变成6的倍数

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int N = 2e5 + 7;
const ll mod = 200907;
using namespace std;

void solve()
{
    ll n;
    cin >> n;
    cout << n * 6ll << ' ' << 3 << '\n';
    cout << 1ll * n << " " << 2ll * n << " " << 3ll * n << '\n';
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
}

int main()
{
    close;
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

I. Takeaway

特判 签到

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
#define int ll
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int N = 2e5 + 7;
const ll mod = 200907;
using namespace std;
int f[8] = {0, 7, 27, 41, 49, 63, 78, 108};
void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    int n;
    cin >> n;
    int sum = 0;
    for (int i = 1; i <= n; i++)
    {
        int a;
        cin >> a;
        sum += f[a];
    }
    if (sum >= 120)
    {
        cout << sum - 50 << "\n";
    }
    else if (sum >= 89)
    {
        cout << sum - 30 << '\n';
    }
    else if (sum >= 69)
    {
        cout << sum - 15 << "\n";
    }
    else
        cout << sum << "\n";
}

signed main()
{
    close;
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

K. City

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int N = 2e5 + 7;
const ll mod = 200907;
using namespace std;
#define int long long
struct node
{
    int x, y;
    int w;
    friend bool operator<(const node &a, const node &b)
    {
        return a.w > b.w;
    }
} edg[N];

struct quest
{
    int id;
    int w;
    int res;
    friend bool operator<(const quest &a, const quest &b)
    {
        return a.w > b.w;
    }
} que[N];

bool cmp(quest a, quest b)
{
    return a.id < b.id;
}

int p[N], siz[N];
int find(int x)
{
    if (p[x] != x)
        p[x] = find(p[x]);
    return p[x];
}

void solve()
{
    int n, m, q;
    cin >> n >> m >> q;
    for (int i = 1; i <= m; i++)
    {
        cin >> edg[i].x >> edg[i].y >> edg[i].w;
    }
    for (int i = 1; i <= q; i++)
    {
        cin >> que[i].w;
        que[i].id = i;
    }
    sort(edg + 1, edg + 1 + m);
    sort(que + 1, que + 1 + q);
    for (int i = 1; i <= n; i++)
    {
        p[i] = i;
        siz[i] = 1;
    }

    // for (int i = 1; i <= n; i++)
    // {
    //     cout << edg[i].w << ' ';
    // }
    // cout << '\n';
    // for (int i = 1; i <= q; i++)
    // {
    //     cout << que[i].w << ' ';
    // }
    // cout << '\n';

    int now = 1, ans = 0;
    for (int i = 1; i <= m; i++)
    {
        if (edg[i].w >= que[now].w)
        {
            int a = edg[i].x;
            int b = edg[i].y;
            if (find(a) == find(b))
            {
                continue;
            }
            // ans -= siz[find(b)] * (siz[find(b)] - 1) / 2;
            // ans -= siz[find(a)] * (siz[find(a)] - 1) / 2;
            ans += siz[find(b)] * siz[find(a)];
            siz[find(b)] += siz[find(a)];
            p[find(a)] = find(b);
            // ans += siz[find(b)] * (siz[find(b)] - 1) / 2;
        }
        else
        {
            que[now].res = ans;
            i--;
            now++;
            if (now > q)
                break;
        }
        // cout << ans << ' ';
    }
    // cout << now << '\n';
    for (int i = now; i <= q; i++)
    {
        // cout << i << "cnm";
        que[i].res = ans;
    }
    // cout << '\n';
    sort(que + 1, que + 1 + q, cmp);
    for (int i = 1; i <= q; i++)
    {
        cout << que[i].res << '\n';
    }
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
}

signed main()
{
    close;
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

M. Master of Shuangpin

写脑残了

#include<stdio.h>
#include<string.h>
char s[2000];
int main() {
	while(gets(s)!=NULL) {
		int n=strlen(s);
		int flag=1;
		for(int i=0; i<n; i++) {
			if(flag==1) {
				flag=0;
				if(s[i+1]==' '||i==n-1){
					printf("%c%c",s[i],s[i]);
					continue;
				}
				else if(s[i+2]==' '||i+1==n-1){
					printf("%c%c",s[i],s[i+1]);
					i++;
					continue;
				}
				
				if(s[i+1]=='h'){
					if(s[i]=='c') {
						if(s[i+2]==' '||i+1==n-1) printf("c");
						printf("i");
						i++;
						continue;
					} else if(s[i]=='s') {
						if(s[i+2]==' '||i+1==n-1) printf("s");
						printf("u");
						i++;
							continue;
					} else if(s[i]=='z') {
						if(s[i+2]==' '||i+1==n-1) printf("z");
						printf("v");
						i++;	continue;
					}
				} else if(s[i+1]=='i') {
					if(s[i]=='a') {
						if(s[i+2]==' '||i+1==n-1) printf("a");
						printf("d");
						i++;	continue;
					} else if(s[i]=='e') {
						if(s[i+2]==' '||i+1==n-1) printf("e");
						printf("w");
						i++;	continue;
					}
				} else if(s[i+1]=='n') {
					if(s[i]=='a'&&s[i+2]!='g') {
						if(s[i+2]==' '||i+1==n-1) printf("a");
						printf("j");
						i++;	continue;
					} else if(s[i]=='a'&&s[i+2]=='g') {
						if(s[i+3]==' '||i+2==n-1) printf("a");
						printf("h");
						i+=2;	continue;
					} else if(s[i]=='e'&&s[i+2]!='g') {
						if(s[i+2]==' '||i+1==n-1) printf("e");
						printf("f");
						i++;	continue;
					}
					else if(s[i]=='e'&&s[i+2]=='g'){
						if(s[i+3]==' '||i+2==n-1) printf("e");
							printf("g");
							i+=2;	continue;
						}
				} else if(s[i+1]=='u') {
					 if(s[i]=='o') {
					 	if(s[i+2]==' '||i+1==n-1) printf("o");
						printf("z");
						i++;	continue;
					}
				} 
				else if(s[i+1]=='o'){
					if(s[i]=='a'){
						if(s[i+2]==' '||i+1==n-1) printf("a");
						printf("c");
						i++;
						continue;
					}
				}
					printf("%c",s[i]);
			} else {
				if(s[i]==' ') {
					printf(" ");
					flag=1;
				} else {
					if(s[i+1]=='h') {
						if(s[i]=='c') {
							printf("i");
							i++;	continue;
						} else if(s[i]=='s') {
							printf("u");
							i++;	continue;
						} else if(s[i]=='z') {
							printf("v");
							i++;	continue;
						}
					} else if(s[i+1]=='i') {
						if(s[i]=='a') {
							printf("d");
							i++;	continue;
						} else if(s[i]=='e') {
							printf("w");
							i++;	continue;
						}
						else if(s[i]=='u'){
							printf("v");
							i++;
							continue;
						}
					} else if(s[i+1]=='n') {
						if(s[i]=='a'&&s[i+2]!='g') {
							printf("j");
							i++;	continue;
						} else if(s[i]=='a'&&s[i+2]=='g') {
							printf("h");
							i+=2;	continue;
						} else if(s[i]=='e'&&s[i+2]!='g') {
							printf("f");
							i++;	continue;
						}
						else if(s[i]=='e'&&s[i+2]=='g'){
							printf("g");
							i+=2;	continue;
						}
						else if(s[i]=='i'){
							if(s[i+2]=='g'){
								printf("k");
								i+=2;	continue;
							}
							else {
								printf("b");
								i+=1;	continue;
							}
						}
						else if(s[i]=='o'){
							if(s[i+2]=='g'){
								i+=2;	
								printf("s");continue;
							}
						}
						else if(s[i]=='u'){
							printf("y");
							i++;
							continue;
						}
					} else if(s[i+1]=='u') {
						if(s[i]=='i') {
							printf("q");
							i++;	continue;
						} else if(s[i]=='o') {
							printf("z");
							i++;	continue;
						}
					}
					else if(s[i+1]=='a'){
						if(s[i]=='u'){
							if(s[i+2]=='n'){
								if(s[i+3]=='g'){
									printf("l");
									i+=3;	continue;
								}
								else{
									printf("r");
									i+=2;	continue;
								}
							}
							else if(s[i+2]=='i'){
								printf("k");
								i+=2;	continue;
							}
							else{
								printf("x");
								i++;	continue;
							}
						}
						else if(s[i]=='i'){
							if(s[i+2]=='n'){
								if(s[i+3]=='g'){
									printf("l");
									i+=3;	continue;
								}
								else{
									printf("m");
									i+=2;	continue;
								}
							}
							else if(s[i+2]=='o'){
								printf("n");
								i+=2;	continue;
							}
							else {
								printf("x");
								i++;	continue;
							}
						}
					}
					else if(s[i+1]=='e'){
						if(s[i]=='i'){
							printf("p");
							i++;	continue;
						}
						else if(s[i]=='u'){
							printf("t");
							i++;	continue;
						}
					}
					else if(s[i+1]=='o'){
						if(s[i]=='u'){
							printf("o");
							i++;	continue;
						}
						else if(s[i]=='a'){
							printf("c");
							i++;	continue;
						}
						else if(s[i]=='i'){
							if(s[i+2]=='n'&&s[i+3]=='g'){
								printf("s");
								i+=3;	continue;
							}
						}
					}  
                        printf("%c",s[i]);
				}
			}
		}
		printf("\n");
	}
}

A. Matrix

组合数 好像有优化 先打完表然后直接输出也行

D. Lowbit

势能线段树

#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN =  3e5+7;
const ll mod = 998244353;
const ll inf = 0x3f3f3f3f;

#define int ll
int a[MAXN];
int lowbit(int x) {
	return x&-x;
}
int bitcnt(int x) {
	int cnt=0;
	while(x) {
		x-=lowbit(x);
		cnt++;
	}
	return cnt;
}
struct Info {
	int sum,cnt;
};
Info operator +(const Info &a,const Info &b) {
	Info c;
	c.sum=a.sum+b.sum;
	c.sum%=mod;
	c.cnt=a.cnt+b.cnt;
	return c;
}
struct node {
	int lazy;
	Info val;
} seg[MAXN<<2];
void up(int id) {
	seg[id].val=seg[id<<1].val+seg[id<<1|1].val;
}
void settag(int id,int l,int r,int val) {
	seg[id].val.sum*=val;
	seg[id].val.sum%=mod;
	seg[id].lazy*=val;
	seg[id].lazy%=mod;
}
void down(int id,int l,int r) {
	if(seg[id].lazy==1) return;
	int mid=l+r>>1;
	settag(id<<1,l,mid,seg[id].lazy);
	settag(id<<1|1,mid+1,r,seg[id].lazy);
	seg[id].lazy=1;
}
void build(int id,int l,int r) {
	seg[id].lazy=1;
	if(l==r) {
		seg[id].val.sum=a[l];
		seg[id].val.cnt=bitcnt(a[l]);
		return;
	}
	int mid = l+r>>1;
	build(id<<1,l,mid);
	build(id<<1|1,mid+1,r);
	up(id);
}
void change(int id,int l,int r,int pos) {
	if(r<pos||l>pos) return;
	if(l==r&&l==pos) {
		int k=lowbit(seg[id].val.sum);
		if(seg[id].val.cnt==1)
			seg[id].val.sum*=2,seg[id].val.sum%=mod;
		else seg[id].val.sum+=k,seg[id].val.cnt=bitcnt(seg[id].val.sum);
		return;
	}
	int mid=l+r>>1;
	down(id,l,r);
	change(id<<1,l,mid,pos);
	change(id<<1|1,mid+1,r,pos);
	up(id);
}
void modify(int id,int l,int r,int ql,int qr) {
	if (ql<=l&&r<=qr) {
		if(seg[id].val.cnt==r-l+1)
		settag(id,l,r,2);
		else{
			for(int i=l;i<=r;i++) change(id,l,r,i);
		}
		return;
	}
	down(id,l,r);
	int mid =(l+r) >> 1;
	if (qr<=mid)
		modify(id <<1,l,mid,ql,qr);
	else if (ql>mid)
		modify(id<<1|1, mid+1,r,ql,qr);
	else {
		modify(id<<1,l,mid,ql,qr);
		modify(id<<1|1,mid+1,r,ql,qr);
	}
	up(id);
}

Info query(int id,int l ,int r,int ql,int qr) {
	if(ql<=l&&r<=qr) {
		return seg[id].val;
	}
	down(id,l,r);
	int mid=l+r>>1;
	if(qr<=mid) return query(id<<1,l,mid,ql,qr);
	else if(ql>mid) return query(id<<1|1,mid+1,r,ql,qr);
	else return query(id<<1,l,mid,ql,qr)+query(id<<1|1,mid+1,r,ql,qr);
}
void solve() {
	int n;
	cin>>n;
	for(int i=1; i<=n; i++) cin>>a[i];
	build(1,1,n);
//	cout<<"# \n";
//	for(int i=1;i<=n;i++) cout<<query(1,1,n,i,i).sum<<" "<<query(1,1,n,i,i).cnt<<"\n";
	int q;
	cin>>q;
	while(q--) {
		int op,l,r;
		cin>>op>>l>>r;
		if(op==1) {
			modify(1,1,n,l,r);
		} else {
			cout<<query(1,1,n,l,r).sum%mod<<"\n";
		}
	}
}
signed main() {
	close;
	int t;
	cin>>t;
	while(t--)
		solve();
}

H. Loneliness

J. Transform

7.2021 Jiangxi Provincial Collegiate Programming Contest

赛时过题ABHJKL补题FG

A. Mio visits ACGN Exhibition

从左上角到右下角 有多少条路径的1和0满足要求

dp i j k 现在的位置ij,现在路径的1数量的方案数

滚动数组优化下空间

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
	std::ios::sync_with_stdio(false); \
	cin.tie(0);                       \
	cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int N = 2e5 + 7;
const ll mod = 998244353;
using namespace std;
ll dp[2][502][1002];
int mp[502][502];
void solve() {
	//	freopen("data.in.txt","r",stdin);
	//	freopen("data.out.txt","w",stdout);
	int m, n, p, q;
	cin >> n >> m >> p >> q;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++)
			cin >> mp[i][j];
	}
	if (p + q > n + m) {
		cout << "0";
		return;
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (i == 1 && j == 1) {
				dp[i%2][j][mp[i][j]] = 1;
				continue;
			}
			if (mp[i][j]== 0)
				for (int k = 0; k < i + j; k++) {
					dp[i%2][j][k] = dp[(i - 1)%2][j][k] + dp[i%2][(j - 1)][k];
					dp[i%2][j][k]%=mod;
			//		cout<<dp[i%2][j][k]<<" ";
				}
			else
				for (int k = 0; k < i + j; k++) {
					if(k==0) {
						dp[i%2][j][k]=0;
						continue;
					}
					dp[i%2][j][k] = dp[(i - 1)%2][j][k - 1] + dp[i%2][(j - 1)][k - 1];
					dp[i%2][j][k]%=mod;
	//			cout<<dp[i%2][j][k]<<" ";
				}
		}
	//	cout<<'\n';
	}
	ll ans=0;
	for(int i=q; i<n+m-p; i++) {
		ans+=dp[n%2][m][i];
	//	cout<<dp[n%2][m][i]<<"\n";
		ans%=mod;
	}
	cout << ans<<"\n";
}

int main() {
	close;
	int t = 1;
	// cin>>t;
	while (t--) {
		solve();
	}
	return 0;
}

B. Continued Fraction

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int N = 2e2 + 7;
const ll mod = 200907;
using namespace std;
// int fac[N];
// void init()
// {
//     for (int i = 1; i < N; i++)
//     {
//         fac[i] = fac[i - 1] + i * i;
//     }
// }
void solve()
{
    int x, y;
    vector<int> ans;
    cin >> x >> y;
    while (1)
    {
        // cout << x << " " << y << '\n';
        ans.push_back(x / y);
        x %= y;
        if (x == 1)
            break;
        swap(x, y);
    }
    ans.push_back(y);
    cout << ans.size() - 1 << ' ';
    // if (x!=0)
    //     ans.push_back(y);
    // cout << ans.size() - 1 << ' ';
    for (auto x : ans)
    {
        cout << x << " ";
    }
    cout << '\n';
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
}

int main()
{
    // init();
    close;
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

H. Hearthstone So Easy

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int N = 2e2 + 7;
const ll mod = 200907;
using namespace std;
// int fac[N];
// void init()
// {
//     for (int i = 1; i < N; i++)
//     {
//         fac[i] = fac[i - 1] + i * i;
//     }
// }
void solve()
{
    int n, k, fir = 0;
    cin >> n >> k;
    // if(n==1)fir=1;
    if (n > 1 && n <= 1 + k)
    {
        fir = 1;
    }
    puts(fir > 0 ? "pllj" : "freesin");
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
}

int main()
{
    // init();
    close;
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

J. LRU

二分空间大小 check里面O(n)跑就行了 很快

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define int long long
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int N = 2e5+ 7;
const ll mod = 200907;
using namespace std;

int n, k, a[N];
queue<pair<int, int>> que;
vector<int> X;
int getX(int x)
{
    return lower_bound(X.begin(), X.end(), x) - X.begin();
}
int mp[N], f[N];
bool check(int x)
{
    for (int i = 1; i <= n; i++)
        f[i] = 0, mp[i] = 0;
    int cnt = 0;
    while (que.size())
        que.pop();
    int sz = 0;
    for (int i = 1; i <= n; i++)
    {
        if (f[a[i]] == 1)
        {
            mp[a[i]] = i;
            cnt++;
        }
        else
        {
            sz++;
            f[a[i]] = 1;
            mp[a[i]] = i;
        }
        que.push({i, a[i]});
        while (sz > x)
        {
            int pos = que.front().first;
            int v = que.front().second;
            que.pop();
            if (pos == mp[v])
            {
                sz--;
                f[v] = 0;
            }
        }
        if (cnt >= k)
            return true;
    }
    if (cnt >= k)
        return true;
    else
        return false;
}
int bs1(int l, int r)
{ // 左偏二分
    while (l < r)
    {
        int mid = l + r >> 1;
        // cout << l << " " << r << " " << mid << " ";

        if (check(mid))
        {
            r = mid;
            // cout << "true\n";
        }
        else
        {
            l = mid + 1;
            // cout << "false\n";
        }
    }
    return l;
}
void solve()
{
    cin >> n >> k;
    X.push_back(-1);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        X.push_back(a[i]);
    }
    sort(X.begin(), X.end());
    X.erase(unique(X.begin(), X.end()), X.end());
    for (int i = 1; i <= n; i++)
        a[i] = getX(a[i]);
    int ans = bs1(1, n + 1);
    if (ans != n + 1)
        cout << ans << '\n';
    else
        cout << "cbddl\n";

    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
}

signed main()
{
    close;
    int t = 1;
    // cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

K. Many Littles Make a Mickle

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int N = 2e2 + 7;
const ll mod = 200907;
using namespace std;
int fac[N];
void init()
{
    for (int i = 1; i < N; i++)
    {
        fac[i] = fac[i - 1] + i * i;
    }
}
void solve()
{
    int k, m;
    cin >> k >> m;
    cout << fac[k] * m << '\n';
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
}

int main()
{
    init();
    close;
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

L. It Rains Again

差分数组 找有多少个点覆盖了

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int N = 2e5 + 7;
const ll mod = 200907;
using namespace std;
int suf[N];
int pre[N];
void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        suf[a]++;
        suf[c]--;
    }
    for (int i = 1; i <= 100007; i++)
    {
        pre[i] = pre[i - 1] + suf[i];
    }
    int ans = 0;
    for (int i = 1; i <= 100000; i++)
    {
        if (pre[i] > 0)
        {
            ans++;
            //  cout << "$ " << i << "\n";
        }
    }
    cout << ans;
}

int main()
{
    close;
    int t = 1;
    // cin>>t;
    while (t--)
    {
        solve();
    }
    return 0;
}

F. Four Column Hanoi Tower

打表 然后观察发现 第一次+2 第二次+2

+4+4+4+8+8+8+8这样的 最后要输出一个大数

用py写的

arr = []
ans =[1]
tmp=1
for i in range(1,600):
    tmp*=2
    for j in range(0,i+1):
        arr.append(tmp)

for i in range(1,100000):
    ans.append(ans[i-1]+arr[i-1])

t=int(input())
for i in range(0,t):
    k=int(input())
    print(ans[k-1])

G. Magic Number Group

找最多的连续的因数出现的次数 就像众数

那就用莫队

#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN =  1e6+700;
const ll mod = 1e9+7;
const ll inf = 0x3f3f3f3f;
#define int ll
bool isPri[MAXN]={1,1};//质数0 
int prime[MAXN];	int cnt=0;
void getPrime(){

	for(int i=2;i<=MAXN-5;i++){
		if(isPri[i]==0)  prime[++cnt]=i;
		for(int j=1;j<=cnt;j++){
			if(i*prime[j]>MAXN-5) break;
			isPri[i*prime[j]]=1;
			if(i%prime[j]==0) break;
		}
	}
} 
struct node{
	int L,R,k; 
}q[MAXN];
int pos[MAXN];
int a[MAXN];
int res[MAXN];
int ans=0,mx;	int n,m;
int coun[MAXN],ct[MAXN];
vector<int> vec[MAXN];
void init(){
	for(int i=1;i<=n;i++){
		int tmp=a[i];
		for(int j=1;j<cnt;j++){
			if(j*j>a[i]) break;
			if(tmp%prime[j]==0)  vec[i].push_back(prime[j]);
			while(tmp%prime[j]==0) tmp/=prime[j];
			if(tmp==1) break; 
		}
		if(tmp!=1) vec[i].push_back(tmp);
	}
}
bool cmp(node a,node b){
	if(pos[a.L]!=pos[b.L]) return pos[a.L]<pos[b.L];
	if(pos[a.L]&1) return a.R>b.R;
	return a.R<b.R; 
}
void add(int x){
	for(auto &it:vec[x]){
		ct[coun[it]]--;
		coun[it]++;
		ct[coun[it]]++;
		if(coun[it]>ans) ans=coun[it];
	}
}
void del(int x){
	for(auto &it:vec[x]){
		ct[coun[it]]--;
		coun[it]--;
		ct[coun[it]]++;
	}
	if(ct[ans]==0&&ans!=0) ans--;
}
void solve(){
	ans=0;
    cin>>n>>m;
	int B=n/sqrt(m)+1;
	for(int i=1;i<=n;i++) cin>>a[i];
	init();
	for(int i=1;i<=m;i++){
		cin>>q[i].L>>q[i].R;
		q[i].k=i; 
	}
	for(int i=1;i<=n;i++){
		pos[i]=(i-1)/B+1;
	}
	sort(q+1,q+1+m,cmp);
	int L=1,R=0;
	for(int i=1;i<=m;i++){
		while(L>q[i].L) add(--L);
		while(R<q[i].R) add(++R);
		while(L<q[i].L) del(L++);
		while(R>q[i].R) del(R--);
		res[q[i].k]=ans;
	}
	while(L<=R) del(L++); 
	for(int i=1;i<=m;i++) cout<<res[i]<<"\n";
	for(int i=1;i<=n;i++) vec[i].clear();
}
signed main(){
	close;
	getPrime();
	int t;cin>>t;
	while(t--)
	solve();
}

8.2019-2020 ACM-ICPC Pacific Northwest Regional Contest (Div. 1)

赛时过题ACDEM 补题B

A Radio Prize

换根板子 需要推出一个能换的式子

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int N = 2e5 + 7;
const ll mod = 998244353;
using namespace std;
#define int ll
int dp[2][N]; // sum path lenth
// int dp1[N];
// sz path lenth
int f[2][N];
int sum[N], sz[N];
int a[N];
vector<pair<int, int>> adj[N];
void dfs_down(int u, int fa)
{
    sz[u] = 1;
    sum[u] = a[u];
    int faw = 1;
    for (auto &it : adj[u])
    {
        int v = it.first, w = it.second;
        if (v == fa)
        {
            continue;
        }
        dfs_down(v, u);
        sz[u] += sz[v];
        sum[u] += sum[v];
        dp[0][u] += dp[0][v] + sum[v] * w;
        dp[1][u] += dp[1][v] + sz[v] * w;
    }
}
void dfs_up(int u, int fa)
{
    for (auto &it : adj[u])
    {
        int v = it.first, w = it.second;
        if (v == fa)
            continue;
        f[0][v] = f[0][u] + (sum[1] - 2 * sum[v]) * w;
        f[1][v] = f[1][u] + (sz[1] - 2 * sz[v]) * w;
        dfs_up(v, u);
    }
}
void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    for (int i = 1; i < n; i++)
    {
        int u, v, w;
        cin >> u >> v >> w;
        adj[u].push_back({v, w});
        adj[v].push_back({u, w});
    }
    dfs_down(1, 0);
    f[1][1] = dp[1][1];
    f[0][1] = dp[0][1];
    // cout<<"# "<<dp[1][1]<<' '<<dp[0][1]<<"\n";
    dfs_up(1, 0);
    for (int i = 1; i <= n; i++)
    {
        cout << f[1][i] * a[i] + f[0][i] << "\n";
    }
}

signed main()
{
    close;
    int t = 1;
    // cin>>t;
    while (t--)
    {
        solve();
    }
    return 0;
}

C Coloring Contention

找最大颜色变换的次数 那从末尾开始dfs 然后找最短路径就行了

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int N = 2e5 + 7;
const ll mod = 998244353;
using namespace std;
vector<int> adj[N];
int d[N], vis[N];
queue<int> que;
void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    int n, m;
    cin >> n >> m;
    for(int i=1;i<=n;i++) d[i]=1e9+7;
    for (int i = 1; i <= m; i++)
    {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    d[n] = 0;
    vis[n] = 1;
    que.push(n);
    while (que.size())
    {
        int u = que.front();
        que.pop();
        for (auto v : adj[u])
        {
            if (d[v] > d[u] + 1)
            {
                d[v] = d[u] + 1;
            }
            if (!vis[v])
            {
                que.push(v);
                vis[v] = 1;
            }
        }
    }
    cout << d[1]-1;
}

signed main()
{
    close;
    int t = 1;
    // cin>>t;
    while (t--)
    {
        solve();
    }
    return 0;
}

D Dividing by Two

贪心 不停整除 小了就加

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int N = 2e5 + 7;
const ll mod = 998244353;
using namespace std;

ll a, b;

void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    cin >> a >> b;
    ll ans = 0;
    while (a > b)
    {
        if (a % 2 == 0)
            a /= 2;
        else
            a++;
        ans++;
    }
    ans += b - a;
    cout << ans << endl;
}

signed main()
{
    close;
    int t = 1;
    // cin>>t;
    while (t--)
    {
        solve();
    }
    return 0;
}

E Rainbow Strings

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int N = 2e5 + 7;
const ll mod = 11092019;
using namespace std;

string s;
int cnt[30];

void solve()
{
    string s;
    cin >> s;
    for (auto x : s)
    {
        cnt[x - 'a']++;
    }
    ll ans = 1;
    for (int i = 0; i < 26; i++)
    {
        ans *= (cnt[i] + 1);
        ans %= mod;
    }
    cout << ans << '\n';
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    cin >> s;
}

signed main()
{
    close;
    int t = 1;
    // cin>>t;
    while (t--)
    {
        solve();
    }
    return 0;
}

M Maze Connect

找菱形的个数和由.开始搜索的连通块数量



#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int N = 1e3 + 7;
const ll mod = 998244353;
using namespace std;

int row, col;
char mp[N][N];
int vis[N][N];

int dx[4] = {-1, 0, 0, 1};
int dy[4] = {0, -1, 1, 0};
int ex[4] = {-1, 1, -1, 1};
int ey[4] = {-1, -1, 1, 1};

void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    cin >> row >> col;
    int ans = 0;
    for (int i = 1; i <= row; i++)
        for (int j = 1; j <= col; j++)
            cin >> mp[i][j];
    if (row == 1)
    {
        for (int i = 1; i <= col; i++)
            if (mp[1][i] != '.')
                ans++;
        cout << ans << endl;
        return;
    }
    if (col == 1)
    {
        for (int i = 1; i <= row; i++)
            if (mp[i][1] != '.')
                ans++;
        cout << ans << endl;
        return;
    }
    // if(row==1&&col==1&&mp[1][1]!='.')cout<<1<<'\n';
    // if (mp[1][2] == '\\')
    //     cout << 'k' << endl;
    for (int i = 1; i <= row; i++)
        for (int j = 1; j <= col; j++)
        {
            if (mp[i][j] == '.' && vis[i][j] == 0)
            {
                bool flag = true;
                queue<pair<int, int>> q;
                q.push({i, j});
                while (q.size())
                {
                    int x = q.front().first, y = q.front().second;
                    q.pop();
                    // if (i == 2 && j == 2)
                    //     cout << x << ' ' << y << endl;
                    if (x <= 1 || y <= 1 || x >= row || y >= col)
                    {
                        flag = false;
                        continue;
                    }
                    if (vis[x][y] == 1)
                        continue;
                    vis[x][y] = 1;
                    for (int i = 0; i < 4; i++)
                    {
                        int xx = x + dx[i];
                        int yy = y + dy[i];
                        if (mp[xx][yy] != '\\' && mp[xx][yy] != '/')
                            q.push({xx, yy});
                    }
                    if (mp[x - 1][y - 1] != '\\' && mp[x - 1][y - 1] != '/')
                        if (mp[x][y - 1] != '/')
                            q.push({x - 1, y - 1});
                    if (mp[x - 1][y + 1] != '\\' && mp[x - 1][y + 1] != '/')
                        if (mp[x][y + 1] != '\\')
                            q.push({x - 1, y + 1});
                    if (mp[x + 1][y - 1] != '\\' && mp[x + 1][y - 1] != '/')
                        if (mp[x][y - 1] != '\\')
                            q.push({x + 1, y - 1});
                    if (mp[x + 1][y + 1] != '\\' && mp[x + 1][y + 1] != '/')
                        if (mp[x][y + 1] != '/')
                            q.push({x + 1, y + 1});
                }
                if (flag)
                    ans++;
            }
        }

    for (int i = 1; i < row; i++)
        for (int j = 1; j < col; j++)
            if (mp[i][j] == '/' && mp[i + 1][j] == '\\' && mp[i][j + 1] == '\\' && mp[i + 1][j + 1] == '/')
                ans++;
    cout << ans << endl;
}

signed main()
{
    close;
    int t = 1;
    // cin>>t;
    while (t--)
    {
        solve();
    }
    return 0;
}

B Perfect Flush

单调栈板子题 没看出来

9.The 13th Chinese Northeast Collegiate Programming Contest

赛时过题BCEGHJ 补题DF

B. Balanced Diet

每个糖果选的个数不能少于limi或者不选

S为总的贡献值 C为数量最大的种类 的数量

求S/C最大

前缀和求出每种糖果在有i个时的值 然后遍历i

记得break 复杂度为O(n)

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
#define int ll
const double pi = 3.141592653589793;
const int N = 2e5 + 7;
const ll mod = 998244353;
using namespace std;
int l[N];
int prel[N];
vector<int> pre[N];
struct node{
	int len;
	int id;
}Node[N];
bool bj(node a,node b){
	return a.len>b.len;
}
void solve()
{
	int n,m;cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>l[i];
	}
	for(int i=1;i<=m;i++){
		Node[i].id=i;
		
	}
	for(int i=1;i<=n;i++){
		int x,ty;cin>>x>>ty;
		pre[ty].push_back(x);
		Node[ty].len++;
	}
	prel[0]=m;
	for(int i=1;i<=m;i++){
		sort(pre[i].begin(),pre[i].end(),greater<int>());
		for(int j=1;j<min(l[i],Node[i].len);j++){
			pre[i][j]=pre[i][j]+pre[i][j-1];
		}
	}
	for(int i=1;i<=m;i++){
		prel[Node[i].len+1]--;
	}
	for(int i=1;i<=n;i++) prel[i]=prel[i-1]+prel[i];
	sort(Node+1,Node+m+1,bj);
	double ans=0.0;
	int ansx,ansy;int fz=0;
	for(int c=1;c<=n;c++){
		for(int now=1;now<=prel[c];now++){
			if(c<l[Node[now].id]) continue;
			fz+=pre[Node[now].id][c-1];
		}
		if(fz==0) continue;
		if(fz*1.0/c>ans){
			ans=fz*1.0/c;
			ansx=fz;
			ansy=c;
		}
	}
	int k=__gcd(ansx,ansy);
	ansx/=k;
	ansy/=k;
	cout<<ansx<<"/"<<ansy<<"\n";
	for(int i=1;i<=n;i++) prel[i]=0;
	for(int i=1;i<=m;i++) {
		pre[i].clear();
		Node[i].len=0;
	}
}

signed main()
{
    close;
    int t = 1;
    cin>>t;
    while (t--)
    {
        solve();
    }
    return 0;
}

C. Line-line Intersection

求有交点的线段的个数 做了非正解 不太好 精度要开-22

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int N = 2e5 + 7;
const ll inf = 0x3f3f3f3f;
const ll mod = 998244353;
const double eps = 1e-22;
using namespace std;
#define int ll
#define double long double
struct node
{
    double k;
    double b;
} edge[N];
bool bj(node a, node b)
{
    if (fabs(a.k - b.k) <= eps)
    {
        return a.b < b.b;
    }
    else
        return a.k < b.k;
}
void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        int ax, ay, bx, by;
        cin >> ax >> ay >> bx >> by;
        if (bx != ax)
            edge[i].k = (by - ay) * 1.0 / (bx - ax) ,edge[i].b = ay - edge[i].k * ax;
        else
            edge[i].k = inf * 1.0,edge[i].b=ax;
    }
    sort(edge + 1, edge + n + 1, bj);
    ll ans = n * (n - 1) / 2, sav = 1, tol = 1, tmp = 0;
    for (int i = 2; i <= n; i++)
    {
        if (fabs(edge[i].k - edge[i - 1].k) >= eps)
        {
            tmp += sav * (sav - 1) / 2;
            // cerr << tol << " " << tmp << '\n';
            ans -= tol * (tol - 1) / 2 - tmp;
            // cout << "ans:" << ans << '\n';
            tol = 1;
            sav = 1;
            tmp = 0;
        }
        else if (fabs(edge[i].k - edge[i - 1].k) < eps && fabs(edge[i].b - edge[i - 1].b) < eps)
        {
            // cout<<"had ";
            tol++;
            sav++;
        }
        else
        {
            // cout << "sav:" << sav << '\n';
            tmp += sav * (sav - 1) / 2;
            sav = 1;
            tol++;
        }
    }
    tmp += sav * (sav - 1) / 2;
    // cerr << tol << " " << sav << '\n';

    ans -= tol * (tol - 1) / 2 - tmp;
    cout << ans << "\n";
}

signed main()
{
    close;
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

E. Minimum Spanning Tree

把树的边看成点 然后建图 最小生成树

每个子节点里面一层都是完全图 完全图里所有边都取一次 然后最小的取n-1次就行了

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int N = 2e5 + 7;
const ll mod = 998244353;
using namespace std;
#define int long long
vector<pair<int, int>> G[N];
int d[N];
void solve()
{
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        G[i].clear();
        d[i] = 0;
    }
    for (int i = 1; i < n; i++)
    {
        int x, y, w;
        cin >> x >> y >> w;
        G[x].push_back({y, w});
        G[y].push_back({x, w});
        d[x]++;
        d[y]++;
    }
    int ans = 0;
    for (int i = 1; i <= n; i++)
    {
        int sum = 0, minn = 1000000000000000;
        if (d[i] == 1)
            continue;
        if (d[i] == 2)
        {
            for (auto it : G[i])
            {
                int x = it.first, y = it.second;
                sum += y;
                minn = min(minn, y);
            }
            ans += sum;
            continue;
        }
        for (auto it : G[i])
        {
            int x = it.first, y = it.second;
            sum += y;
            minn = min(minn, y);
        }
        sum += minn * (d[i] - 2);
        ans += sum;
    }
    cout << ans << '\n';
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
}

signed main()
{
    close;
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

G. Radar Scanner

二分写的 找x和y让大家最小的区间

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int N = 2e5 + 7;
const ll inf = 1e9;
const ll mod = 998244353;
using namespace std;

int n;
struct rec
{
    ll x1, y1, x2, y2;
} rc[N];

struct qujian
{
    ll l, r;
} qj[N];

int find(ll pos)
{
    // cout << pos << endl;
    // for (int i = 1; i <= n; i++)
    //     cout << qj[i].l << ' ' << qj[i].r << endl;
    int cntl = 0, cntr = 0;
    for (int i = 1; i <= n; i++)
    {
        if (qj[i].r < pos)
            cntl++;
        else if (pos < qj[i].l)
            cntr++;
    }
    // cout << cntl << ' ' << cntr << endl;

    if (cntl >= cntr)
        return -1;
    else
        return 1;
}

ll count()
{
    ll l = 0, r = inf + 10, mid;
    while (l <= r)
    {
        mid = l + r >> 1;
        int op = find(mid);
        // cout << op << endl;
        // if (op == 0)
        //     break;
        if (op == -1)
            r = mid - 1;
        else
            l = mid + 1;
        // cout << l << ' ' << r << endl;
    }

    // cout << mid << endl;
    // cout << l << endl;
    ll ans = 0, mn;
    for (int i = 1; i <= n; i++)
    {
        if (qj[i].r < r)
            ans += r - qj[i].r;
        else if (r < qj[i].l)
            ans += qj[i].l - r;
    }
    mn = ans;
    ans = 0;
    for (int i = 1; i <= n; i++)
    {
        if (qj[i].r < l)
            ans += l - qj[i].r;
        else if (l < qj[i].l)
            ans += qj[i].l - l;
    }
    mn = min(mn, ans);
    return mn;
}

void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> rc[i].x1 >> rc[i].y1 >> rc[i].x2 >> rc[i].y2;
    for (int i = 1; i <= n; i++)
        qj[i].l = rc[i].x1, qj[i].r = rc[i].x2;
    ll ans = 0;
    ans += count();

    for (int i = 1; i <= n; i++)
        qj[i].l = rc[i].y1, qj[i].r = rc[i].y2;
    ans += count();
    cout << ans << endl;
}

signed main()
{
    close;
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

H. Skyscraper

建造大楼 会有操作抬升楼

最小建造次数的算法是所有上升 的长度的和

就是对每个点求它和上一个点的差 大于0有贡献

抬升区间(L-R) 只会改变L点和R+1点的贡献

用树状数组维护新数组和贡献

#include<bits/stdc++.h>
#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int N = 4e5 + 7;
const ll mod = 998244353;
using namespace std;
#define int ll
int t[N],a[N],t2[N];
int lowbit(int x){
	return x&-x;
}
ll getsum(int x){
	ll sum=0;
	while(x){
		sum+=t[x];
		x-=lowbit(x);
	}
	return sum;
}
void addv(int x,int val){
	while(x<=100005){
		t[x]+=val;
		x+=lowbit(x);
	}
}
ll getsum2(int x){
	ll sum=0;
	while(x){
		sum+=t2[x];
		x-=lowbit(x);
	}
	return sum;
}
void addv2(int x,int val){
	while(x<=100005){
		t2[x]+=val;
		x+=lowbit(x);
	}
}
void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    memset(t,0,sizeof(t));
    memset(t2,0,sizeof(t));
    int n,m;cin>>n>>m;
    for(int i=1;i<=n;i++){
    	cin>>a[i];
	}
	for(int i=1;i<=n;i++){
		if(a[i]-a[i-1]>0) addv(i,a[i]-a[i-1]);
	}
	while(m--){
		int op;cin>>op;
		if(op==1){
			int l,r,x;cin>>l>>r>>x;
			addv2(l,x);
			addv2(r+1,-x);
			if(a[l]+getsum2(l)-a[l-1]-getsum2(l-1)>0){
				int tmp = getsum(l)-getsum(l-1);
				addv(l,a[l]+getsum2(l)-a[l-1]-getsum2(l-1)-tmp);
			}
			if(a[r]+getsum2(r)-a[r+1]-getsum2(r+1)>0){
				int tmp=getsum(r+1)-getsum(r);
				addv(r+1,tmp*-1);
			}
			else{
				int tmp=getsum(r+1)-getsum(r);
				addv(r+1,tmp*-1);
				addv(r+1,a[r+1]+getsum2(r+1)-(a[r]+getsum2(r)));
			}
		}
		else {
			int l,r;cin>>l>>r;
			cout<<a[l]+getsum2(l)+getsum(r)-getsum(l)<<"\n";
		}
//		for(int i=1;i<=n;i++){
//			cout<<a[i]+getsum2(i)<<" ";
//		}
//		cout<<'\n';
	}
}

signed main()
{
   close;
    int t = 1;
    cin>>t;
    while (t--)
    {
        solve();
    }
    return 0;
}

J. Time Limit

签到 找tle时间

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int N = 2e5 + 7;
const ll mod = 998244353;
using namespace std;

void solve()
{
    int n;
    cin >> n;

    vector<int> a(n + 10);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    int ans = a[1] * 3;
    for (int i = 2; i <= n; i++)
    {
        ans = max(ans, a[i] + 1);
    }
    if (ans % 2)
        cout << ans + 1 << '\n';
    else
        cout << ans << '\n';
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
}

signed main()
{
    close;
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

D. Master of Data Structure

场上还在瞎写

2000次询问 是个虚树题 建虚树暴力跑时间完全够

#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN =  5e5+7;
const ll mod = 1e9+7;
const ll inf = 0x3f3f3f3f;
#define int ll 
vector<array<int,4> > Q;
vector<int> adj[MAXN],vg[MAXN];
int par[MAXN][20],dep[MAXN];
int f[MAXN];
int w[MAXN];//u点向上的权值
int a[MAXN];
int d[MAXN];
//par[u][i]代表点u的祖先中 深度为max(1,dep[u]-2^i)是谁
int in[MAXN],out[MAXN],tim=0;
void dfs(int u,int fa) {
	dep[u]=dep[fa]+1;
	par[u][0]=fa;
	for(int i=1; i<20; ++i) {
		par[u][i]=par[par[u][i-1]][i-1];
	}
	for(auto &v:adj[u]) {
		if(v==fa) continue;
		dfs(v,u);
	}
}
int getLCA(int u,int v) {
	if(dep[u]<dep[v]) swap(u,v);
	for(int i=19; i>=0; --i) {
		if(dep[par[u][i]]>=dep[v]) u=par[u][i];
	}
	if(u==v) return u;
	for(int i=19; i>=0; i--) {
		if(par[u][i]!=par[v][i]) {
			u=par[u][i];
			v=par[v][i];
		}
	}
	return par[u][0];
}
void init(int u,int fa) {
	in[u]=++tim;
	for(auto v:adj[u]) {
		if(v==fa) continue;
		init(v,u);
	}
	out[u]=tim;
}
int isp(int u, int v) {
	return in[u] <= in[v] && out[v] <= out[u];
}
bool cmp(int u, int v) {
	return in[u] < in[v];
}
void build(vector<int>&node) {
	sort(node.begin(), node.end(), cmp);
	set<int>node_st;
	for (int x : node)node_st.insert(x);
	for (int i = 1; i < node.size(); i++)node_st.insert(getLCA(node[i - 1], node[i]));
	node.clear();
	for (int x : node_st)node.push_back(x);
	sort(node.begin(), node.end(), cmp);
	vector<int> st;
	for (int v : node) {
		while (!st.empty() && !isp(st.back(), v))
			st.pop_back();
		if (!st.empty()) {
			vg[st.back()].push_back(v);
		}

		st.push_back(v);
	}
}
void dfs2(int u,int fa) {
	d[u]=d[fa]+1;
	f[u]=fa;
	for(auto &v:vg[u]) {
		if(v==fa) continue;
		dfs2(v,u);
	}
}
//node.push_back(1)
//build(node);
void work(int u,int v,int k,int op) {
	int ans=0;
	if(op==1) {
		while(u!=v) {
			assert(u&&v);
			if(d[u]>d[v]) {
				a[u]+=k;
				w[u]+=k;
				u=f[u];
			} else {
				a[v]+=k;
				w[v]+=k;
				v=f[v];
			}
		}
		a[u]+=k;
	} else if(op==2) {
		while(u!=v) {
			assert(u&&v);
			if(d[u]>d[v]) {
				a[u]^=k;
				w[u]^=k;
				u=f[u];
			} else {
				a[v]^=k;
				w[v]^=k;
				v=f[v];
			}
		}
		a[u]^=k;
	} else if(op==3) {
		while(u!=v) {
			assert(u&&v);
			if(d[u]>d[v]) {
				if(a[u]>=k)
					a[u]-=k;
				if(w[u]>=k)
					w[u]-=k;
				u=f[u];
			} else {
				if(a[v]>=k)
					a[v]-=k;
				if(w[v]>=k)
					w[v]-=k;
				v=f[v];
			}
		}
		if(a[u]>=k) a[u]-=k;
	} else if(op==4) {
		while(u!=v) {
			assert(u&&v);
			if(d[u]>d[v]) {
				ans+=(dep[u]-dep[f[u]]-1)*w[u]+a[u];
				u=f[u];
			} else {
				ans+=(dep[v]-dep[f[v]]-1)*w[v]+a[v];
				v=f[v];
			}
		}
		ans+=a[u];
		cout<<ans<<"\n";
	} else if(op==5) {
		while(u!=v) {
			assert(u&&v);
			if(d[u]>d[v]) {
				ans^=a[u];
				if((dep[u]-dep[f[u]]-1)%2==1) ans^=w[u];
				u=f[u];
			} else {
				ans^=a[v];
				if((dep[v]-dep[f[v]]-1)%2==1) ans^=w[v];
				v=f[v];
			}
		}
		ans^=a[u];
		cout<<ans<<"\n";

	} else if(op==6) {
		int mins=a[u],maxs=a[u];
		while(u!=v) {
			assert(u&&v);
			if(d[u]>d[v]) {
				mins=min(mins,a[u]);
				if((dep[u]-dep[f[u]]-1))
					mins=min(mins,w[u]);
				maxs=max(maxs,a[u]);
				if((dep[u]-dep[f[u]]-1))
					maxs=max(maxs,w[u]);
				u=f[u];
			} else {
				mins=min(mins,a[v]);
				if((dep[v]-dep[f[v]]-1))
					mins=min(mins,w[v]);
				maxs=max(maxs,a[v]);
				if((dep[v]-dep[f[v]]-1))
					maxs=max(maxs,w[v]);
				v=f[v];
			}
		}
		mins=min(mins,a[u]);
		maxs=max(maxs,a[u]);
		ans=maxs-mins;
		cout<<ans<<'\n';

	} else if(op==7) {
		ans=inf;
		while(u!=v) {
			assert(u&&v);
			if(d[u]>d[v]) {
				ans=min(ans,abs(a[u]-k));
				if((dep[u]-dep[f[u]]-1))
					ans=min(ans,abs(w[u]-k));
				u=f[u];
			} else {
				ans=min(ans,abs(a[v]-k));
				if((dep[v]-dep[f[v]]-1))
					ans=min(ans,abs(w[v]-k));
				v=f[v];
			}
		}
		ans=min(ans,abs(a[u]-k));
		cout<<ans<<"\n";
	}
}
void solve() {
	int n,q;
	cin>>n>>q;
	vector<int> node;
	Q.clear();
	tim=0;
	for(int i=1; i<=n; i++) {
		for(int j=0; j<20; j++) par[i][j]=0;
		adj[i].clear();
		vg[i].clear();
		a[i]=0;
		w[i]=0;
		dep[i]=0;
		d[i]=0;
	}
	for(int i=1; i<n; i++) {
		int u,v;
		cin>>u>>v;
		adj[u].push_back(v);
		adj[v].push_back(u);
	}
	dfs(1,0);
	init(1,0);
	set<int> sta;
	for(int i=1; i<=q; i++) {
		int op;
		cin>>op;
		if(op==1||op==2||op==3||op==7) {
			int u,v,k;
			cin>>u>>v>>k;
			Q.push_back({op,u,v,k});
			sta.insert(u);
			sta.insert(v);
		} else {
			int u,v;
			cin>>u>>v;
			Q.push_back({op,u,v,0});
			sta.insert(u);
			sta.insert(v);
		}
	}
	sta.insert(1);
	assert(sta.size() <= 6000);
	for(auto &it:sta) node.push_back(it);
	build(node);
	dfs2(1,0);
	for(int i=0; i<q; i++) {
		int op=Q[i][0],u=Q[i][1],v=Q[i][2],k=Q[i][3];
		work(u,v,k,op);
//		cout<<"TEST : \n";
//		for(int i=1; i<=n; i++) {
//			cout<<"a: "<<a[i]<<" w: "<<w[i]<<"\n";
//		}
	}
}
signed main() {
    close;
	int t;
	cin>>t;
	while(t--)
		solve();
}

F. Mini-game Before Contest

图上博弈 写SG函数一样的操作

10.The 10th Shandong Provincial Collegiate Programming Contest

赛时过题ACDFLM 补题EHIK

A. Calandar

给出日历规定 算新日历

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <cstring>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int inf = 2e9;
const int N = 2e5 + 7;
const ll mod = 998244353;
using namespace std;

ll y, m, d, cnt;
string a[5] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday"};
string s;

void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    cin >> y >> m >> d;
    cnt = d;
    cin >> s >> y >> m >> d;
    cnt = d - cnt;
    cnt %= 5;
    cnt = (cnt + 5) % 5;
    // cout << cnt << endl;
    int pos = 0;
    for (int i = 0; i < 5; i++)
        if (a[i] == s)
        {
            pos = i;
            break;
        }
    pos += cnt;
    pos %= 5;
    cout << a[pos] << endl;
}

signed main()
{
    close;
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

C. Wandering Robot

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <cstring>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int inf = 2e9;
const int N = 2e5 + 7;
const ll mod = 998244353;
using namespace std;

ll len, n;
string s;

void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    ll mx = 0;
    ll x = 0, y = 0;
    cin >> len >> n >> s;
    for (int i = 0; i < len; i++)
    {
        if (s[i] == 'U')
            y++;
        else if (s[i] == 'D')
            y--;
        else if (s[i] == 'L')
            x--;
        else if (s[i] == 'R')
            x++;
        mx = max(mx, abs(x) + abs(y));
    }
    x *= (n - 1);
    y *= (n - 1);
    for (int i = 0; i < len; i++)
    {
        if (s[i] == 'U')
            y++;
        else if (s[i] == 'D')
            y--;
        else if (s[i] == 'L')
            x--;
        else if (s[i] == 'R')
            x++;
        mx = max(mx, abs(x) + abs(y));
    }
    cout << mx << endl;
}

signed main()
{
    close;
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

D. Game on a Graph

取的最多个数就是m-n+1 看看谁取下一个 另一个团队的人就赢了

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <cstring>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int inf = 2e9;
const int N = 2e5 + 7;
const ll mod = 998244353;
using namespace std;

void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    int k;
    cin>>k;
    string s;cin>>s;s=" "+s;
    int n,m;cin>>n>>m;
    for(int i=1;i<=m;i++){
    	int u,v;cin>>u>>v;
	}
	int tmp=m-n+1;
	tmp++;
	tmp=(tmp-1)%k+1;
	if(s[tmp]=='1') cout<<"2\n";
	else cout<<"1\n";
	
}

signed main()
{
    close;
    int t = 1;
    cin>>t;
    while (t--)
    {
        solve();
    }
    return 0;
}

F. Stones in the Bucket

让所有数字一样 至少需要几步

贪心 最少步数的时候肯定是每个数在到达可能最大的平均值

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <cstring>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
#define int ll
const double pi = 3.141592653589793;
const int inf = 2e9;
const int N = 2e5 + 7;
const ll mod = 998244353;
using namespace std;
int a[N];
void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    int n;cin>>n;
    int sum=0;
    for(int i=1;i<=n;i++){
    	cin>>a[i];
    	sum+=a[i];
	}
	int ans=0;
	sum/=n;
	for(int i=1;i<=n;i++){
		if(a[i]>sum){
			ans+=a[i]-sum;
		}
	}
	cout<<ans<<'\n';
}

signed main()
{
    close;
    int t = 1;
     cin>>t;
    while (t--)
    {
        solve();
    }
    return 0;
}

L. Median

给定数大小关系 看某个数是否可能变成中位数

用弗洛伊德算法求传递凸包,如果一个数到达它的数不超过n/2 它到达的也不超过n/2就可以

如果某个数既能到达它 它又能到达 那就是不可能的

(无视这个tarjan

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <cstring>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double pi = 3.141592653589793;
const int inf = 0x3f3f3f3f;
const int N = 2e5 + 7;
const ll mod = 998244353;
using namespace std;
int ans[N];
int d[105][105];
int cnt;
int low[N], num[N], dfn;
int sccno[N], sta[N], top;
vector<int> G[N];
void dfs(int u)
{
    sta[top++] = u;
    low[u] = num[u] = ++dfn;
    for (int i = 0; i < G[u].size(); i++)
    {
        int v = G[u][i];
        if (!num[v])
        {
            dfs(v);
            low[u] = min(low[v], low[u]);
        }
        else if (!sccno[v])
        {
            low[u] = min(low[u], num[v]);
        }
    }
    if (low[u] == num[u])
    {
        cnt++;
        while (1)
        {
            int v = sta[--top];
            sccno[v] = cnt;
            if (u == v)
                break;
        }
    }
}
void Tarjan(int n)
{
    cnt = top = dfn = 0;
    memset(sccno, 0, sizeof sccno);
    memset(num, 0, sizeof num);
    memset(low, 0, sizeof low);
    for (int i = 1; i <= n; i++)
    {
        if (!num[i])
        {
            dfs(i);
        }
    }
}

void solve()
{
    int n, m, vaild = 1;
    cin >> n >> m;
    memset(d, 0x3f3f3f3f, sizeof(d));
    for (int i = 0; i <= n; i++)
    {
        G[i].clear();
    }
    for (int i = 1; i <= m; i++)
    {
        int x, y;
        cin >> x >> y;
        if (x == y)
            vaild = 0;
        G[y].push_back(x); // taj
        d[x][y] = 1;
    }

    Tarjan(n);
    if (cnt != n)
        vaild = 0;

    if (vaild == 0)
    {
        for (int i = 1; i <= n; i++)
        {
            cout << '0';
        }
        cout << '\n';
        return;
    }
    for (int k = 1; k <= n; k++)
    {
        for (int u = 1; u <= n; u++)
        {
            for (int v = 1; v <= n; v++)
            {
                d[u][v] = min(d[u][v], d[u][k] + d[k][v]);
            }
        }
    }
    for (int i = 1; i <= n; i++)
    {
        int In = 0, Out = 0;
        for (int j = 1; j <= n; j++)
        {
            if (i == j)
                continue;
            if (d[i][j] != inf && d[j][i] != inf)
                vaild = 0;
            if (d[i][j] != inf)
                In++;
            if (d[j][i] != inf)
                Out++;
            if (In <= (n / 2) && Out <= (n / 2))
                ans[i] = 1;
            else
                ans[i] = 0;
        }
    }
    if (vaild == 0)
    {
        for (int i = 1; i <= n; i++)
        {
            cout << '0';
        }
        cout << '\n';
        return;
    }
    for (int i = 1; i <= n; i++)
        cout << ans[i];
    cout << "\n";
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
}

signed main()
{
    close;
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

M. Sekiro

钱的数量超出就直接输出1 其他的暴力跑 复杂度不高

#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <cstring>
#include <algorithm>
#include <iomanip> //fixed<<setprecision(12)<<
#include <utility> //pair模板
#include <cmath>
#include <random> //mt19937 mtrand(time(0));
#include <time.h>
#define close                         \
    std::ios::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
#define int long long
const double pi = 3.141592653589793;
const int inf = 2e9;
const int N = 2e5 + 7;
const ll mod = 998244353;
using namespace std;
int fac[40];
void init()
{
    fac[0] = 1;
    for (int i = 1; i <= 30; i++)
    {
        fac[i] = fac[i - 1] * 2;
    }
}
void solve()
{
    int n;
    int k;
    cin >> n >> k;
    if (n == 0)
    {
        cout << 0 << "\n";
        return;
    }
    if (k >= 31)
    {
        cout << 1 << '\n';
        return;
    }
    for (int i = 1; i <= k; i++)
    {
        if (n % 2)
            n = n / 2 + 1;
        else
            n /= 2;
    }

    cout << n << '\n';
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
}

signed main()
{
    close;
    init();
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

E. BaoBao Loves Reading

和之前那个好像 但是不能那样想

这次要考虑某一个数有贡献的条件是容量大于中间不同数的数量

那么我们就算出每一个数什么时候有贡献就行了

经典树状数组扫描线求数种类

#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN =  3e5+7;
const ll mod = 1e9+7;
const ll inf = 0x3f3f3f3f;
int last[MAXN],ans[MAXN]; 
struct BIT {
	int t[MAXN]={0};
	BIT(){
		memset(t,0,sizeof(t));
	}
	int lowbit(int x) {
		return x&-x;
	}
	ll getsum(int x) {
		ll sum=0;
		while(x) {

			sum+=t[x];
			x-=lowbit(x);
		}
		return sum;
	}
	void addv(int x,int val) {
		while(x<=MAXN) {
			t[x]+=val;
			x+=lowbit(x);
		}
	}
};
void solve(){
	BIT T;
	int n;cin>>n;
	for(int i=1;i<=n;i++) last[i]=0,ans[i]=0;
	for(int i=1;i<=n;i++){
		int x;cin>>x;
		if(last[x]==0){
			T.addv(i,1);
		}
		else{
			T.addv(last[x],-1);
			T.addv(i,1);
			int sum=T.getsum(i)-T.getsum(last[x]-1);
			ans[sum]++;
		}
		last[x]=i;
	}
	for(int i=1;i<=n;i++) ans[i]=ans[i-1]+ans[i];
	for(int i=1;i<=n;i++) {
		cout<<n-ans[i];
		if(i!=n) cout<<" ";
	}
	cout<<'\n'; 
}
signed main(){
    close;
	int t;cin>>t;
	while(t--)
	solve();
}

H. Tokens on the Segments

每个线段放一个石头就会贡献+1,但是不能在一个位置放两个石头,问最多贡献

用set模拟也可以做

用优先队列方便 先取最左边的 可以取就丢掉 不能取就把它的头-1

#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN =  3e5+7;
const ll mod = 1e9+7;
const ll inf = 0x3f3f3f3f;
#define int ll
priority_queue<pair<int,int> > que;
void solve(){
	int n;cin>>n; 
	while(que.size()) que.pop();
	for(int i=1;i<=n;i++){
		int l,r;cin>>l>>r;
		que.push({l*-1,r*-1});
	}
	int ans=0,now=0;
	while(que.size()){
		auto st=que.top();
		que.pop();
		if(st.first*-1>now){
			now=st.first*-1;
			ans++;
		}
		else {
			int x=st.first;
			x*=-1;
			x++;
			int y=st.second;
			y*=-1;
			if(x>y);
			else que.push({x*-1,y*-1});
		}
	}
	cout<<ans<<'\n';
}
signed main(){
    close;
	int t;cin>>t;
	while(t--)
	solve();
}

I. Connected Intervals

要统计出符合条件的区间的数量,意思是(L,R)是从L-R的所有点

只看这些点的时候 如果连通块数量是1 就符合条件

考虑扫描线 在加入一个数 3 的时候 假设3是一个完全独立的点 不与其他数相连 所有区间 如(1,3),(2,3),(3,3)的连通块数量都会+1

但是如果告诉你 3和2连接 那3加入(2,3)的时候 其实连通块数量没有+1 那就给2,3的数量-1 然后1,3的同理也要-1

设线段树上的点 1 2 3 4 ...... 表示区间的左端点 扫到3 就表示到3位为止的区间,然后up的时候统计线段内最小值和最小值的数量

如果最小值==1 就return cnt,意思就是让线段树来找为1 的点的个数

#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
#define int ll
typedef long long ll;
const ll MAXN =  3e5+7;
const ll mod = 1e9+7;
const ll inf = 0x3f3f3f3f;
vector<int> adj[MAXN];
struct Info {
	int mn,cnt;
};
Info operator +(const Info &a,const Info &b) {
	Info c;
	c.mn=min(a.mn,b.mn);
	c.cnt=0;
	if(c.mn==a.mn) c.cnt+=a.cnt;
	if(c.mn==b.mn) c.cnt+=b.cnt;
	return c;
}
struct node {
	int lazy;
	Info val;
} seg[MAXN<<2];
void up(int id) {
	seg[id].val=seg[id<<1].val+seg[id<<1|1].val;
}
void settag(int id,int l,int r,int tag) {
	seg[id].val.mn+=tag;
	seg[id].lazy+=tag;
}
void down(int id,int l,int r) {
	if(seg[id].lazy==0) return;
	int mid=l+r>>1;
	settag(id<<1,l,mid,seg[id].lazy);
	settag(id<<1|1,mid+1,r,seg[id].lazy);
	seg[id].lazy=0;
}
void build(int id,int l,int r) {
	seg[id].lazy=0;
	seg[id].val.cnt=0;
	if(l==r) {
		seg[id].val.mn=0;
		seg[id].val.cnt=1;
		return;
	}
	int mid = l+r>>1;
	build(id<<1,l,mid);
	build(id<<1|1,mid+1,r);
	up(id);
}
void modify(int id,int l,int r,int ql,int qr,int val) {
	if (ql==l&&r==qr) {
		settag(id,l,r,val);
		return;
	}
	down(id,l,r);
	int mid =(l+r) >> 1;
	if (qr<=mid)
		modify(id <<1,l,mid,ql,qr,val);
	else if (ql>mid)
		modify(id<<1|1, mid+1,r,ql,qr,val);
	else {
		modify(id<<1,l,mid,ql,mid,val);
		modify(id<<1|1,mid+1,r,mid+1,qr,val);
	}
	up(id);
}
int query(int id,int l ,int r,int ql,int qr) {
	if(ql==l&&r==qr) {
		if(seg[id].val.mn==1)
		return seg[id].val.cnt;
		else return 0;
	}
	down(id,l,r);
	int mid=l+r>>1;
	if(qr<=mid) return query(id<<1,l,mid,ql,qr);
	else if(ql>mid) return query(id<<1|1,mid+1,r,ql,qr);
	else return query(id<<1,l,mid,ql,mid)+query(id<<1|1,mid+1,r,mid+1,qr);
}
void solve() {
	int n;cin>>n;
	build(1,1,n);
	for(int i=1;i<=n;i++){
		adj[i].clear();
	}
	for(int i=1;i<n;i++){
		int u,v;cin>>u>>v;
		adj[u].push_back(v);
		adj[v].push_back(u);
	}
	int ans=0;
	for(int i=1;i<=n;i++){
		modify(1,1,n,1,i,1);
		for(auto &v:adj[i]){
			if(v<i){
				modify(1,1,n,1,v,-1);
			}
		}
		ans+=query(1,1,n,1,i);
	}
	cout<<ans<<"\n";
}
signed main() {
	close;
	int t;cin>>t;
	while(t--) 
	solve();
}

K. Happy Equation

打了个表 发现a为奇数始终输出1

在x>p的时候 我们可以发现 因为a里面至少有一个2的因子,

2的x次方乘上一堆数必定能被2的p次方整除 所以在x>p时 我们求x的a次方%2的p次方为0的数就行了

在x<=p的时候 枚举这个x 统计答案

在x>p的时候 我们需要让x里面2的因数的数量cnt *a>=p 这样就能整除了

然后我们可以算出cnt最少需要多少个

假如说cnt至少需要2个 x是属于(p,2^p)的 就相当于算 p-2^p之间有多少2的2次方(4)的倍数

除一下再减一下就好了

#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN =  3e5+7;
ll mod;
const ll inf = 0x3f3f3f3f;
#define int ll
ll _power(ll a,int b) {
	ll ans=1,res=a;
	while(b) {
		if(b&1)
			ans=ans*res%mod;
		res=res*res%mod;
		b>>=1;
	}
	return ans%mod;
}

void solve() {
	int a,p;
	cin>>a>>p;
	if(a%2==1) {
		cout<<1<<"\n";
		return;
	}
	mod=(1<<p);
	int ans=0;
	for(int x=2; x<=p; x+=2) { //统计x<=p的时候 合法的数量 
		if(_power(a,x)==_power(x,a)) ans++;
	}
	int k=p/a;
	if(k*a!=p) k++;
	ans+=pow(2,p-k);
	int l=p/pow(2,k);
	ans-=l;
	printf("%lld\n",ans);
	//cout<<ans-p/(pow(2,k))<<"\n";//此时必须满足x> p 
}
signed main() {
	int t;
	cin>>t;
	while(t--)
		solve();
}

2023暑期训练后半

1. 2023 Xian Jiaotong University Programming Contest

赛时过题ABCDEFHMN 补题GJO

2. 2019-2020 ACM-ICPC Brazil Subregional Programming Contest

3. 2019 ICPC Universidad Nacional de Colombia Programming

赛时过题BGIK 补CDJ

B. Boring Non-Palindrome

签到 队友写的

void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    cin >> s;
    int n = s.length();
    s = ' ' + s;
    for (int i = 1; i <= n; i++)
    {
        int l = i, r = n;
        while (l <= r)
        {
            if (s[l] == s[r])
            {
                l++, r--;
            }
            else
            {
                break;
            }
        }
        if (r < l)
        {
            cout << s;
            for (int j = i - 1; j > 0; j--)
                cout << s[j];
            return;
        }
    }
}

C. Common Subsequence

类似求最长匹配的dp 队友补了

D. Do Not Try This Problem

并查集+根号分治

间隔长的直接跳就行了 短的用并查集暴力维护下一个跳的

int f[MAXN][320];//用并查集跳边 
int vis[MAXN];
struct node{
	int s,d,p;
	char ch;
}N[MAXN];
void clean(int n){
	for(int j=1;j<=n;j++)
	for(int i=1;i<320;i++){
		f[j][i]=j;
	}
}
int find(int x,int k){
	if(x!=f[x][k]) f[x][k]=find(f[x][k],k);
	return f[x][k];
}
void add(int x,int y,int k){
	int fx=find(x,k),fy=find(y,k);
	if(fx!=fy) f[fx][k]=fy;
}
void solve(){
	string str;cin>>str;
	int n=str.length();
	str=" "+str;
	int k=sqrt(n);
	clean(n);
	int q;cin>>q;
	for(int i=1;i<=q;i++){
		int s,d,p;cin>>N[i].s>>N[i].d>>N[i].p;
		char ch;cin>>N[i].ch;
	}
	for(int i=q;i>=1;i--){
		int s=N[i].s,d=N[i].d,p=N[i].p;
		char ch=N[i].ch;
		if(d>k){
			for(int j=s;j<=min(s+p*d,n);j+=d){
				if(!vis[j]){
					vis[j]=1;
					str[j]=ch;
				}
			}
		}
		else{
			int now=s;
			while(now<=min(s+p*d,n)){
				now=find(now,d);
				if(now>min(s+p*d,n)) break;
				if(!vis[now]){
					vis[now]=1;
					str[now]=ch;
					if(now+d<=n)
					add(now,now+d,d);
					now+=d;
				}
				else{
					if(now+d<=n)
					add(now,now+d,d);
					now+=d;
				}
			}
		}
	//	cout<<i<<str<<"\n";
	}
	for(int i=1;i<=n;i++) cout<<str[i];
}

E. Extreme Image

圆形的扫描线 还没补

F. Fraction Formula

模拟

G. Graduation

struct E
{
    int to, w, next;
} edge[M];
int head[N], tot;
int sz[N];
int n, k;

void add(int u, int v, int w)
{
    tot++;
    edge[tot].to = v;
    edge[tot].w = w;
    edge[tot].next = head[u];
    head[u] = tot;
}

void dfs(int u, int f)
{
    sz[u] = 1;
    for (int i = head[u]; i; i = edge[i].next)
    {
        int v = edge[i].to, w = edge[i].w;
        dfs(v, u);
        sz[u] += sz[v];
    }
}

struct cmp
{
    bool operator()(int &a, int &b)
    {
        return sz[a] < sz[b];
    }
};

void solve()
{
    cin >> n >> k;
    vector<int> s;
    for (int i = 1, f; i <= n; i++)
    {
        cin >> f;
        if (f == 0)
            s.push_back(i);
        add(f, i, 0);
    }
    for (auto i : s)
        dfs(i, 0);
    priority_queue<int, vector<int>, cmp> q;
    for (auto i : s)
        q.push(i);
    int ans = 0;
    while (q.size())
    {
        vector<int> tp;
        for (int i = 1; q.size() && i <= k; i++)
        {
            int u = q.top();
            q.pop();
            for (int i = head[u]; i; i = edge[i].next)
            {
                tp.push_back(edge[i].to);
            }
        }
        for (auto i : tp)
            q.push(i);
        ans++;
    }
    cout << ans;
}

I. Integer Prefix

签到

void solve()
{
    string s;
    cin >> s;
    vector<char> ans;
    for (auto x : s)
    {
        if (x <= '9' && x >= '0')
            ans.push_back(x);
        else
            break;
    }
    if (ans.size() == 0)
        cout << -1 << '\n';
    else
        for (auto x : ans)
        {
            cout << x;
        }
}

J. Jail Destruction

砍墙 势能线段树 但是我势能用错了t了

要算非0的最小值 这样最后是可以执行区间加的 保持势能

#define int ll
int a[MAXN];
struct Info{
	int mn,sum,len;
};
Info operator +(const Info &a,const Info &b){
	Info c;
	c.len=a.len+b.len;
	c.mn=min(a.mn,b.mn);
	c.sum=a.sum+b.sum;
	return c;
}
struct node{
	int lazy;
	Info val;
}seg[MAXN<<2];
void settag(int id,int l,int r,int val){
	seg[id].val.mn+=val;
	seg[id].val.sum+=(seg[id].val.len)*val;
	seg[id].lazy+=val;
}
void up(int id){
	seg[id].val=seg[id<<1].val+seg[id<<1|1].val;
}
void down(int id,int l,int r){
	if(seg[id].lazy==0) return ;
	int mid=l+r>>1;
	settag(id<<1,l,mid,seg[id].lazy);
	settag(id<<1|1,mid+1,r,seg[id].lazy);
	seg[id].lazy=0;
}
void build(int id,int l,int r){
	if(l==r){
		seg[id].val.mn=a[l];
		seg[id].val.len=1;
		seg[id].val.sum=a[l];
		seg[id].lazy=0;
		return;
	}
	int mid=l+r>>1;
	build(id<<1,l,mid);
	build(id<<1|1,mid+1,r);
	up(id);
}
void modify(int id,int l,int r,int ql,int qr,int val){
	if(ql==l&&qr==r&&seg[id].val.mn+val>=0){
		settag(id,l,r,val);
		return;
	}
	if(seg[id].val.len==0) return;
	if(l==r){
		seg[id].val.sum=0;
		seg[id].val.mn=inf;
		seg[id].val.len=0;
		return;
	}
	down(id,l,r);
	int mid=l+r>>1;
	if(qr<=mid) modify(id<<1,l,mid,ql,qr,val);
	else if(ql>mid) modify(id<<1|1,mid+1,r,ql,qr,val);
	else{
		modify(id<<1,l,mid,ql,mid,val);
		modify(id<<1|1,mid+1,r,mid+1,qr,val);
	}
	up(id);
}
Info query(int id,int l,int r,int ql,int qr){
	if(ql==l&&r==qr){
		return seg[id].val;
	}
	down(id,l,r);
	int mid=l+r>>1;
	if(qr<=mid) return query(id<<1,l,mid,ql,qr);
	else if(ql>mid) return query(id<<1|1,mid+1,r,ql,qr);
	else{
		return query(id<<1,l,mid,ql,mid)+query(id<<1|1,mid+1,r,mid+1,qr);
	}
}
void solve()
{
	int n,m;cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	build(1,1,n);
	for(int i=1;i<=m;i++){
		int op;cin>>op;
		if(op==1){
			int l,r;cin>>l>>r;
			if(r>=l) cout<<query(1,1,n,l,r).sum<<"\n";
			else{
				cout<<query(1,1,n,1,r).sum+query(1,1,n,l,n).sum<<"\n";
			}
		}
		else{
			int l,r,w;cin>>l>>r>>w;
			if(r>=l) modify(1,1,n,l,r,-w);
			else{
				modify(1,1,n,1,r,-w);
				modify(1,1,n,l,n,-w);
			}
		}
	}
}

K. Kernel Of Love

签到

void solve()
{
    int n;
    cin >> n;
    if (n == 1)
        cout << 0 << '\n';
    else if (n == 2)
        cout << 0 << '\n';
    else if (n == 3)
        cout << 2 << '\n';
    else if (n == 4)
        cout << 3 << '\n';
    else
        cout << (n - 4) / 3 * 2 + 3 + ((n - 4) % 3 >= 2) << '\n';
}

4. 2018-2019 9th BSUIR Open Programming Championship

赛时过题AEFH 补题IK

A. Four minutes until BSUIR Open

int n;
double a1, a2, x[N], v[N];

double count(double v0, double v1, double x)
{
    double a = (a1 * a1 + a1 * a2);
    double b = 2.0 * v0 * (a1 + a2);
    double c = v0 * v0 - v1 * v1 - 2.0 * a2 * x;
    // cout << a << ' ' << b << ' ' << c << endl;
    double t = (-b + sqrt(b * b - 4.0 * a * c)) / (2.0 * a);
    // cout << t + (v0 - v1 + a1 * t) / a2 << endl;
    return t + (v0 - v1 + a1 * t) / a2;
}

void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    // cout << sqrt(6) << endl;
    cin >> n >> a1 >> a2;
    for (int i = 1; i <= n; i++)
        cin >> x[i] >> v[i];
    for (int i = n; i > 0; i--)
    {
        v[i - 1] = min(v[i - 1], sqrt(2.0 * a2 * (x[i] - x[i - 1]) + v[i] * v[i]));
    }
    for (int i = 0; i < n; i++)
    {
        v[i + 1] = min(v[i + 1], sqrt(2.0 * a1 * (x[i + 1] - x[i]) + v[i] * v[i]));
    }
    double ans = 0;
    for (int i = 1; i <= n; i++)
    {
        ans += count(v[i - 1], v[i], x[i] - x[i - 1]);
    }
    cout << fixed << setprecision(7) << ans << endl;
}

E. Small business

*Edgrass 搓了好久的模拟 类目了 居然给他过了

裱起来(

#include<bits/stdc++.h>
#define ll long long
#define PII pair<int,int>
//  #define int long long
using namespace std;
const ll mod=1e9+7; 
const ll inf=0x3f3f3f3f;  
const ll INF=0x3f3f3f3f3f3f3f3f;  
const double eps=1e-10;  
const int N=2e5+10;
// struct node{
//     friend bool operator<(const node&a,const node&b){
//         return ;
//     }
// }
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;}
inline void write(int x){char F[200];int tmp=x>0?x:-x;if(x<0) putchar('-');int cnt=0;while(tmp>0){F[cnt++]=tmp%10+'0';tmp/=10;}while(cnt>0)putchar(F[--cnt]);}
inline int combination(int n,int k){int sum=0;if (n==k||k==0){return 1;}else{return combination(n-1,k)+combination(n-1,k-1);}}

void solve(){
    string s;
    cin>>s;
    int n=s.size(),cnt0=0;
    vector<int>vec;
    for(auto x:s){
        if(x=='0')cnt0++;
        else vec.push_back(x-'0');
    }
    for(int i=1;i<=n;i++){
        if(i>n-i||(n-i)>19||i>19)continue;
        priority_queue<int,vector<int>,greater<int> >pq;
        for(auto x:vec){
            pq.push(x);
        }
        int cnt=cnt0,ok=1;
        vector<int>ans1,ans2;
        if(n-i==19){
            for(int i=1;i<=18;i++){
                cnt--;
            }
            if(pq.size()==0){
                    ok=0;
                    continue;
                }
            int t=pq.top();
            pq.pop();
            if(cnt<0||t!=1)continue;
            else {
                if(i==1){
                    if(cnt){
                        cnt--;
                        ans1.push_back(0);
                    }
                }
                if(ans1.size()!=i){
                    if(ok==0||pq.size()==0){
                        continue;
                    }
                    ans1.push_back(pq.top());
                    pq.pop();
                    for(int j=2;j<=i&&ok;j++){
                        if(cnt)ans1.push_back(0),cnt--;
                        else if(pq.size()==0){
                            ok=0;   
                            break;
                        }else ans1.push_back(pq.top()),pq.pop();
                    }
                }
                if((ans1[0]!=1||ans1[ans1.size()-1]!=0)&&ans1.size()==19)continue;
                for(auto x:ans1){
                    cout<<x;
                }
                cout<<" 1000000000000000000\n";
            }
            return ;
        }
        if(i==1){
            if(cnt){
                cnt--;
                ans1.push_back(0);
            }
        }
        if(n-i==1){
            if(cnt){
                cnt--;
                ans2.push_back(0);
            }
        }

        if(ans1.size()!=i){
            if(ok==0||pq.size()==0){
                continue;
            }
            ans1.push_back(pq.top());
            pq.pop();
            for(int j=2;j<=i&&ok;j++){
                if(cnt)ans1.push_back(0),cnt--;
                else if(pq.size()==0){
                    ok=0;   
                    break;
                }else ans1.push_back(pq.top()),pq.pop();
            }
        }

        if(ans2.size()!=n-i){
            if(ok==0||pq.size()==0){
                continue;
            }
            ans2.push_back(pq.top());
            pq.pop();
            for(int j=2;j<=(n-i);j++){
                if(cnt)ans2.push_back(0),cnt--;
                else if(pq.size()==0){
                    ok=0;   
                    break;
                }else ans2.push_back(pq.top()),pq.pop();
            }
            if(ok==0||pq.size()!=0||cnt!=0){
                continue;
            }
        }
        if((ans2[0]!=1||ans2[ans2.size()-1]!=0)&&ans2.size()==19)continue;
        if((ans1[0]!=1||ans1[ans1.size()-1]!=0)&&ans1.size()==19)continue;

        for(auto x:ans1){
            cout<<x;
        }
        cout<<" ";
        for(auto x:ans2){
            cout<<x;
        }
        cout<<'\n';
        return ;
    }
    cout<<-1<<" "<<-1<<'\n';
    //puts(ans>0?"YES":"NO");
    //puts(ans>0?"Yes":"No");
}

F. Prime or number

void solve()
{
    int n;
    cin >> n;
    if (n == 1)
    {
        cout << "No\n";
        return;
    }
    int x = n, cnt = 0;
    while (x)
    {
        if (x % 2)
            cnt++;
        x /= 2;
    }
    if (cnt == 1)
        cout << "Yes\n";
    else if (cnt == 2 && n % 2)
        cout << "Yes\n";
    else
        cout << "No\n";
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
}

H. Nonfibonacci numbers

有几个数字固定不会出现 数位dp

int f[N][N][2][2], num[N], now;
int dfs(int pos, int sum, bool lead, bool limit)
{
    int ans = 0;
    if (pos == 0)
        return 1;
    if (f[pos][sum][limit][lead] != -1)
        return f[pos][sum][limit][lead];
    int up = (limit ? num[pos] : 9);
    // cout<<"pos:"<<pos<<" "<<up<<'\n';
    for (int i = 0; i <= up; i++)
    {
        if (i == 1 || i == 2 || i == 3 || i == 5 || i == 8)
            continue;
        if (i == 0 && lead)
            ans += dfs(pos - 1, sum, true, limit &&i == up);
        else
            ans += dfs(pos - 1, sum + 1, false, limit &&i == up);
    }
    f[pos][sum][limit][lead] = ans;
    return ans;
}
void solve()
{
    int n=read();
    int x = n, len = 0;
    while (x)
    {
        num[++len] = x % 10;
        x /= 10;
    }
    memset(f, -1, sizeof f);
    cout << dfs(len, 0, true, true) << '\n';
    //    freopen("data.in.txt","r",stdin);
    //    freopen("data.out.txt","w",stdout);
}

I. Equal Mod Segments

求连续mod 从左到右和从右到左一样的区间个数

用二分求对每个数来说 向下取的区间

线段树补充 - xishuiw - 博客园 (cnblogs.com)

丢这了 扫描线

K. Innovations

垃圾做法 树剖 但是赛场上线段树板子抄错了

ll a[MAXN];
vector<pair<int,ll> > adj[MAXN];
int deep[MAXN],siz[MAXN],hson[MAXN],rak[MAXN],dfn[MAXN],f[MAXN],cnt=0,top[MAXN];
ll ans=0,sum;
void tree_build(int u,int fa,int dep) {
	deep[u]=dep;
	siz[u]=1;
	f[u]=fa;
	for(auto &it:adj[u]) {
		int v=it.first;
		if(v==fa) continue;
		ll w=it.second;
		a[v]=w;
		tree_build(v,u,dep+1);
		siz[u]+=siz[v];
		if(hson[u]==0||siz[v]>siz[hson[u]]) hson[u]=v;
	}
}
void tree_decom(int u,int t) {
	top[u]=t;
	cnt++;
	dfn[u]=cnt;
	rak[cnt]=u;
	if(hson[u]!=0) {
		tree_decom(hson[u],t);
		for(auto &it:adj[u]) {
			int v=it.first;
			if(hson[u]!=v&&v!=f[u]) tree_decom(v,v);
		}
	}
}
struct Info {
	ll sum;
	bool flag;
};
Info operator +(const Info &a,const Info &b) {
	Info c;
	c.flag=(a.flag&b.flag);
	return c;
}
struct node {
	Info val;
} seg[MAXN<<2];
void up(int id) {
	seg[id].val=seg[id<<1].val+seg[id<<1|1].val;
}
void build(int id,int l,int r) {
	if(l==r) {
		seg[id].val.sum=a[rak[l]];
		if(a[rak[l]]==1) seg[id].val.flag=1;
		return;
	}
	int mid=l+r>>1;
	build(id<<1,l,mid);
	build(id<<1|1,mid+1,r);
	up(id);
}
void modify(int id,int l,int r,int ql,int qr,int val) {
	if(seg[id].val.flag==1) return;
	if(ql==l&&r==qr) {
		if(seg[id].val.flag==1) {
			return;
		}
	}
	if(l==r) {
		ll tmp=sqrt(seg[id].val.sum);
		ll temp=seg[id].val.sum-tmp;
		int sizz=siz[rak[l]];
		ans-=(temp)*(sizz)*(sum-sizz);
		ans%=mod;
		if(ans<0) ans+=mod;
		seg[id].val.sum=tmp;
		if(tmp==1) seg[id].val.flag=1;
		return;
	}
	int mid=(l+r)>>1;
	if(qr<=mid) modify(id<<1,l,mid,ql,qr,val);
	else if(ql>mid) modify(id<<1|1,mid+1,r,ql,qr,val);
	else {
		if(seg[id<<1].val.flag!=1)
		modify(id<<1,l,mid,ql,mid,val);
		if(seg[id<<1|1].val.flag!=1)
		modify(id<<1|1,mid+1,r,mid+1,qr,val);
	}
	up(id);
}
void dfs(int u,int fa) {
	for(auto &it:adj[u]) {
		int v=it.first;
		if(v==fa) continue;
		ans+=a[v]*(siz[v])*(sum-siz[v]);
		if(ans>mod)
		ans%=mod;
		dfs(v,u);
	}
}
void solve() {
	int n,q;
	scanf("%d %d",&n,&q);
	sum=n;
	for(int i=1; i<n; i++) {
		int u,v;
		ll w;
		scanf("%d %d %lld",&u,&v,&w);
		adj[u].push_back({v,w});
		adj[v].push_back({u,w});
	}
	tree_build(1,0,0);
	tree_decom(1,1);
	dfs(1,0);
	build(1,1,n);
	printf("%lld\n",ans);
	for(int i=1; i<=q; i++) {
		int u,v;
		scanf("%d %d",&u,&v);
		if(u==v||seg[1].val.flag==1) {
			printf("%lld\n",ans);
			continue;
		}
		while(top[u]!=top[v]) {
			if(deep[top[u]]>deep[top[v]]) {
				modify(1,1,n,dfn[top[u]],dfn[u],1);
				u=f[top[u]];
			} else {
				modify(1,1,n,dfn[top[v]],dfn[v],1);
				v=f[top[v]];
			}
		}
		if(dfn[v]!=dfn[u]) {
			if(dfn[v]<dfn[u]) swap(u,v);
			modify(1,1,n,dfn[u]+1,dfn[v],1);
		}

		printf("%lld\n",ans);
	}
}

5. 2019-2020 Winter Petrozavodsk Camp, Day 8: Almost Algorithmic Contest

只写了FG的超难场

6. 2020-2021 ACM-ICPC Brazil Subregional Programming Contest

赛时过题:ABFGL 补题:EHN(I)

A. Sticker Album

概率dp 一直想不明白怎么搞的样例 然后发现从0开始推

用前缀和(滑动窗口)优化速度

对于a==0的样例xlen/(len-) 就行了

半蒙的

void solve() {
	int n,a,b;
	cin>>n>>a>>b;
	
	for(int i=1; i<=n; i++) {
		int l=i-b;
		int r=i-a;
		if(i<=a) dp[i]=1;
		else {
			if(l>0){
				if(a!=0)
				dp[i]=(pre[r]-pre[l-1]+r-l+1)/(b-a+1);
				else{
					dp[i]=(pre[r-1]-pre[l-1]+(r-l+1))/(b-a+1);
					dp[i]*=(b-a+1)*1.0/(b-a);
				}
			}
			else{
				if(a!=0)
				dp[i]=(pre[r]+r-l+1)/(b-a+1);
				else{
					dp[i]=(pre[r-1]+r-l+1)/(b-a+1);
					dp[i]*=(b-a+1)*1.0/(b-a);
				}
			}
		}

		pre[i]=pre[i-1]+dp[i];
	//	cout<<"i "<<i<<" :"<<dp[i]<<"\n";
	}
	printf("%.8f",dp[n]);
}

B. Battleship

队友签到的

int mp[20][20], n;
 
void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        int d, l, r, c;
        cin >> d >> l >> r >> c;
        for (int i = 0; i < l; i++)
        {
            int x = r, y = c;
            if (d == 0)
                y += i;
            else
                x += i;
            if (x > 10 || y > 10 || mp[x][y] == 1)
            {
                cout << "N";
                return;
            }
            mp[x][y] = 1;
        }
    }
    cout << "Y";
}

E. Party Company

扫描线 赛场没写出来

树状数组维护符合的下界数量

int t[MAXN];
int lowbit(int x) {
	return x&-x;
}
ll getsum(int x) {
	ll sum=0;
	while(x) {
 
		sum+=t[x];
		x-=lowbit(x);
	}
	return sum;
}
void addv(int x,int val) {
	while(x<=MAXN) {
		t[x]+=val;
		x+=lowbit(x);
	}
}
struct E {
	int to,w,next;
} edge[M];
int head[N],tot;
 
void add(int u,int v,int w) {
	tot++;
	edge[tot].to=v;
	edge[tot].w=w;
	edge[tot].next=head[u];
	head[u]=tot;
}
int fa[N][20];
int w[MAXN];
vector<int> node[MAXN];
int ans[MAXN],far[MAXN];
void dfs(int u,int f) {
	fa[u][0]=f;
	for(int i=1; i<20; i++)fa[u][i]=fa[fa[u][i-1]][i-1];
 
	for(int i=head[u]; i; i=edge[i].next) {
		int v=edge[i].to,w=edge[i].w;
		if(v==f)continue;
		dfs(v,u);
	}
}
int gettop(int u,int mx) {
	for(int i=19; i>=0; i--) {
		if(w[fa[u][i]]<=mx)u=fa[u][i];
	}
	return u;
}
 
void calc(int u,int fa) {
	for(auto &it:node[u]) {
		addv(it,1);
	}
	ans[u]=getsum(w[u]);
	for(int i=head[u]; i; i=edge[i].next) {
		int v=edge[i].to;
		if(v==fa) continue;
		calc(v,u);
	}
	for(auto &it:node[u]) {
		addv(it,-1);
	}
}
void solve() {
	int n,m;
	cin>>n>>m;
	for(int i=1; i<=n; i++) {
		int u;
		cin>>w[i]>>u;
		if(i!=1)
			add(i,u,1);
		add(u,i,1);
		far[i]=u;
	}
	far[1]=0;
	dfs(1,1);
	for(int i=1; i<=m; i++) {
		int u,l,r;
		cin>>u>>l>>r;
		int top=gettop(u,r);
		node[top].push_back(l);
	}
	calc(1,1);
	for(int i=1; i<=n; i++) cout<<ans[i]<<" ";
}
 

F. Fastminton

模拟

string s;
 
void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    int ls = 0, rs = 0, lcnt = 0, rcnt = 0, tag = 0;
 
    cin >> s;
    // bool flag=true;
    for (int i = 0; i < s.length(); i++)
    {
 
        if (s[i] == 'Q')
        {
            if (ls == 2)
                printf("2 (winner) - %d\n", rs);
            else if (rs == 2)
                printf("%d - 2 (winner)\n", ls);
            else if (tag == 0)
                printf("%d (%d*) - %d (%d)\n", ls, lcnt, rs, rcnt);
            else
                printf("%d (%d) - %d (%d*)\n", ls, lcnt, rs, rcnt);
        }
        if (ls == 2 || rs == 2)
            continue;
 
        if (s[i] == 'S')
        {
            if (tag == 0)
                lcnt++;
            else
                rcnt++;
        }
        else if (s[i] == 'R')
        {
            tag = 1 - tag;
            if (tag == 0)
                lcnt++;
            else
                rcnt++;
        }
        if (lcnt == 10 || lcnt >= 5 && lcnt >= rcnt + 2)
        {
            ls++;
            lcnt = rcnt = 0;
        }
        else if (rcnt == 10 || rcnt >= 5 && rcnt >= lcnt + 2)
        {
            rs++;
            lcnt = rcnt = 0;
        }
    }
}

G. Game Show

最大前缀和 签到

H. SBC's Hangar

每个数倍数差都在2以上

意思就是 从小到大排序后 大的那个的数量 小的所有加起来都取不到

用二进制表示是否取这个

因此可以输出最大的能表示的范围内的二进制情况

然后也能得到 最小的满足范围下界的二进制

对其中的式子进行数位dp

#define int ll
int a[MAXN];
int upper[MAXN];int n,k;
int dp[60][2][60];
ll dfs(int pos,int pre_num,int c,int flag){
	int max_number;
	if(pos<=0) return c==k;
	if(!flag&&dp[pos][pre_num][c]!=-1) return dp[pos][pre_num][c];
	if(flag) max_number=upper[pos];
	else max_number=1;
	ll ret=0;
	for(int i=0;i<=max_number;i++){

		ret+=dfs(pos-1,i,c+i,flag&&(i==max_number));
		
	}
	if(!flag) dp[pos][pre_num][c]=ret;
	return ret;
}
void solve(){
	cin>>n>>k;
	for(int i=1;i<=n;i++) cin>>a[i];
	sort(a+1,a+1+n);
	int l,r;cin>>l>>r;
	int tmp=r;
	for(int i=n;i>=1;i--){
		if(a[i]<=tmp){
			upper[i]=1;
			tmp-=a[i];
		}
		else upper[i]=0;
	}
	for(int i=0;i<=n;i++){
		for(int j=0;j<=1;j++){
			for(int x=0;x<=n;x++) dp[i][j][x]=-1;
		}
	}
	int ans=dfs(n,0,0,1);
	tmp=0;
	int cnt=0;
	for(int i=n;i>=1;i--){
		int temp=0;
			for(int j=1;j<i;j++){
				temp+=a[j];
			}
		if(temp+tmp<l){
			tmp+=a[i];
			upper[i]=1;
			cnt++;
		}
		else upper[i]=0;
	}
	for(int i=0;i<=n;i++){
		for(int j=0;j<=1;j++){
			for(int x=0;x<=n;x++) dp[i][j][x]=-1;
		}
	}
	if(cnt==k&&tmp>=l) ans++;
	ans-=dfs(n,0,0,1);
	cout<<ans;
}

I. Interactivity

树dp 队友式子推对了但是用逆元的组合数就错了

N. Number Multiplication

套了个n1/4的分解质因数的板子就过了

就板子 不贴了 毛的

7. 2018-2019 ACM-ICPC Brazil Subregional Programming Contest

赛时CDEFIL 补题BG

B. Marbles

博弈

C. Pizza Cutter

扫描线 就逆序对那个

如果加了一条线多了a个交点 那么方块的个数多a+1

扫两遍就行

因为只有Li>Lj&&Ri<Rj的才有交点 很好统计

#define int ll
int t[MAXN];
int lowbit(int x) {
	return x&-x;
}
ll getsum(int x) {
	ll sum=0;
	while(x) {
		sum+=t[x];
		x-=lowbit(x);
	}
	return sum;
}
void addv(int x,int val) {
	while(x<MAXN) {
		t[x]+=val;
		x+=lowbit(x);
	}
}
vector<int> X;
int getX(int x) {
	int k=lower_bound(X.begin(),X.end(),x)-X.begin();
	return k;
}
struct node{
	int x,y;
}N[MAXN];
bool bj(node a,node b){
	return a.x>b.x;
}
void solve() {
	int x,y;
	cin>>x>>y;
	int n,m;cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>N[i].x>>N[i].y;
		X.push_back(N[i].x);
		X.push_back(N[i].y);
	}
	X.push_back(inf*-1);
	sort(X.begin(),X.end());
	X.erase(unique(X.begin(),X.end()),X.end());
	int ans=1;
	sort(N+1,N+1+n,bj);
	for(int i=1;i<=n;i++){
		int a=N[i].x;
		int b=N[i].y;
		b=getX(b);
		ans+=1+getsum(b);
		addv(b,1);
	}
	memset(t,0,sizeof(t));
	X.clear();
	for(int i=1;i<=m;i++){
		cin>>N[i].x>>N[i].y;
		X.push_back(N[i].x);
		X.push_back(N[i].y);
	}
	X.push_back(inf*-1);
	sort(X.begin(),X.end());
	X.erase(unique(X.begin(),X.end()),X.end());
	sort(N+1,N+1+m,bj);
	for(int i=1;i<=m;i++){
		int a=N[i].x;
		int b=N[i].y;
		b=getX(b);
		ans+=1+getsum(b);
		addv(b,1);
	}
	ans+=n*m;
	cout<<ans;
}

D. Unraveling Monty Hall

队友签到的


void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    int n, a, ans = 0;
    cin >> n;
    while (n--)
    {
        cin >> a;
        if (a > 1)
            ans++;
    }
    cout << ans;
}


E. Enigma

对每个字母扫 它的贡献值算在字符串的头上

计算有几个字符串位置的头贡献是0就行了

int len[MAXN];
void solve()
{
   string a,b;cin>>a>>b;
   int na=a.length(),nb=b.length();
   b=" "+b;
   a=" "+a;
   int st=na-nb;
   for(int i=1;i<=nb;i++){
   		for(int j=i;j<=st+i;j++){
   			if(a[j]==b[i]){
   				len[j-i+1]++;
   		//		cout<<b[i]<<" "<<j-i+1<<"\n";
			   }
		   }
   }
   int ans=0;
   for(int i=1;i<=st+1;i++){
   	if(len[i]==0) ans++;
   }
   cout<<ans;
}

F. Music Festival

每个舞会至少选一个人 表演时间不能重合 求最大贡献

状压dp

vector<array<int,3> >g[86405];
int f[86405][1100];
void solve(){
    int n=read();
    for(int i=1;i<=n;i++){
        int k=read();
        for(int j=1;j<=k;j++){
            int x=read(),y=read(),w=read();
            g[y].push_back((array<int,3>){x,w,i});
        }
    }
    for(int i=1;i<=86400;i++){
        for(int j=0;j<(1<<(n));j++){
            f[i][j]=f[i-1][j];
            for(auto it:g[i]){
                int l=it[0],w=it[1],k=it[2]-1;
                if(((j>>k)&1)&&(f[l][j-(1<<k)]>0))f[i][j]=max(f[i][j],f[l][j-(1<<k)]+w);
                if((((j&(((1<<n)-1)-(1<<k)))==0))||(f[l][(j&(((1<<n)-1)-(1<<k)))]>0))f[i][j]=max(f[i][j],f[l][(j&(((1<<n)-1)-(1<<k)))]+w);
            }
        }
    }
    // cerr<<1<<'\n';
    int ans=0;
    for(int i=1;i<=86400;i++){
        ans=max(ans,f[i][(1<<(n))-1]);
    }
    if(ans==0)cout<<-1<<'\n';
    else cout<<ans<<'\n';
    //puts(ans>0?"YES":"NO");
    //puts(ans>0?"Yes":"No");
}

G. Gasoline

二分+网络流

不会写 队友补了

I. Switches

最多做两边就知道结果了

模拟一下

int aim[N], n, m, p[N];
vector<int> a[N];

bool check()
{
    for (int i = 1; i <= m; i++)
    {
        if (aim[i] != p[i])
            return false;
    }
    return true;
}

void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    cin >> n >> m;
    int l;
    cin >> l;
    for (int i = 1; i <= l; i++)
    {
        int tp;
        cin >> tp;
        aim[tp] = 1;
    }
    for (int i = 1; i <= n; i++)
    {
        int num, tp;
        cin >> num;
        for (int j = 1; j <= num; j++)
        {
            cin >> tp;
            a[i].push_back(tp);
        }
    }
    int ans = 0;
    for (int i = 1; i <= n * 2; i++)
    {
        int id = (i - 1) % n + 1;
        for (auto pos : a[id])
            p[pos] ^= 1;
        ans++;
        if (check())
        {
            cout << ans << endl;
            return;
        }
    }
    // for (int i = 1; i <= m; i++)
    //     cout << p[i] << ' ';
    // cout << endl;
    cout << -1 << endl;
}


J. Joining Capitals

听说是最小斯坦纳树 先学学

L. Subway Lines

树剖 区间0/1翻转 统计全数1的个数 就可以算出变成0的个数

听讲题发现做麻烦了

using namespace std;
#define int ll
int deep[MAXN],siz[MAXN],f[MAXN],hson[MAXN],dfn[MAXN],top[MAXN],cnt=0,rdfn[MAXN],rak[MAXN];
vector<int> adj[MAXN];
struct Info{
	int sum;
};
Info operator +(const Info &a,const Info &b){
	Info c;
	c.sum=a.sum+b.sum;
	return c;
};
struct node{
	int lazy;
	Info val;
}seg[MAXN<<2];
void up(int id){
	seg[id].val=seg[id<<1].val+seg[id<<1|1].val;
}
void settag(int id,int l,int r,int tag){
	seg[id].val.sum=r-l+1-seg[id].val.sum;
	seg[id].lazy^=1;
}
void down(int id,int l,int r){
	if(seg[id].lazy==0) return;
	int mid=l+r>>1;
	settag(id<<1,l,mid,seg[id].lazy);
	settag(id<<1|1,mid+1,r,seg[id].lazy);
	seg[id].lazy=0;
}
void build(int id,int l,int r){
	if(l==r){
		seg[id].val.sum=0;
		seg[id].lazy=0;
		return;
	}
	int mid=l+r>>1;
	build(id<<1,l,mid);
	build(id<<1|1,mid+1,r);
	up(id);
}
void modify(int id,int l,int r,int ql,int qr,int val){
	if(ql==l&&r==qr){
		settag(id,l,r,val);
		return;
	}
	down(id,l,r);
	int mid=l+r>>1;
	if(qr<=mid) modify(id<<1,l,mid,ql,qr,val);
	else if(ql>mid) modify(id<<1|1,mid+1,r,ql,qr,val);
	else{
		modify(id<<1,l,mid,ql,mid,val);
		modify(id<<1|1,mid+1,r,mid+1,qr,val);
	}
	up(id);
}
Info query(int id,int l,int r,int ql,int qr){
	if(ql==l&&r==qr) return seg[id].val;
	down(id,l,r);
	int mid=l+r>>1;
	if(qr<=mid) return query(id<<1,l,mid,ql,qr);
	else if(ql>mid) return query(id<<1|1,mid+1,r,ql,qr);
	else{
		return query(id<<1,l,mid,ql,mid)+query(id<<1|1,mid+1,r,mid+1,qr);
	}
}
void tree_build(int u,int fa,int dep){
	deep[u]=dep;
	siz[u]=1;
	f[u]=fa;
	hson[u]=0;
	for(auto &v:adj[u]){
		if(v==fa) continue;
		tree_build(v,u,dep+1);
		siz[u]+=siz[v];
		if(hson[u]==0||siz[v]>siz[hson[u]]) hson[u]=v;
	}
}
void tree_decom(int u,int t){
	top[u]=t;
	cnt++;
	dfn[u]=cnt;
	rak[cnt]=u;
	if(hson[u]!=0){
		tree_decom(hson[u],t);
		for(auto &v:adj[u]){
			if(hson[u]!=v&&v!=f[u]) tree_decom(v,v);
		}
	}
	rdfn[u]=cnt;
}
int getlca(int u,int v){
	while(top[u]!=top[v]){
		if(deep[top[u]]>deep[top[v]]) u=f[top[u]];
		else v=f[top[v]];
	}
	return deep[u]>deep[v]?v:u;
}int n,m;
void calc(int u,int v){
		while(top[u]!=top[v]) {
			
			if(deep[top[u]]>deep[top[v]]) {
				modify(1,1,n,dfn[top[u]],dfn[u],1);
				u=f[top[u]];
			} else {
				modify(1,1,n,dfn[top[v]],dfn[v],1);
				v=f[top[v]];
			}
		}
			if(dfn[v]<dfn[u]) swap(u,v);		
			modify(1,1,n,dfn[u],dfn[v],1);
//		cout<<"* ";
//		for(int i=1;i<=n;i++){
//			cout<<query(1,1,n,i,i).sum<<" ";
//		}
//		cout<<"\n";
}
void solve()
{
	cin>>n>>m;
	for(int i=1;i<n;i++){
		int u,v;cin>>u>>v;
		adj[u].push_back(v);
		adj[v].push_back(u);
	}
	tree_build(1,0,0);
	tree_decom(1,1);
//	for(int i=1;i<=n;i++) cout<<dfn[i]<<" ";
//		for(int i=1;i<=n;i++) cout<<top[i]<<" ";
//	cout<<"\n";
	build(1,1,n);
	while(m--){
		int u,v,p,q;
		cin>>u>>v;
		calc(u,v);
		int len1=deep[u]+deep[v]-deep[getlca(u,v)]*2+1;
		cin>>p>>q;
		calc(p,q);
		int len2=deep[p]+deep[q]-deep[getlca(p,q)]*2+1;
		int ans=len1+len2-query(1,1,n,1,n).sum;
		ans/=2;
		cout<<ans<<'\n';
		calc(u,v);
		calc(p,q);
	}
   
}

M. Modifying SAT

赛时写的2-sat 好像是高斯消元 晚点补

8. 2020-2021 Winter Petrozavodsk Camp, Day 5: Almost Retired Dandelion Contest (XXI Open Cup, Grand Prix of Nizhny Novgorod)

赛时过题:GJM 补题A

A. Assignment Problem

回溯法 暴力搜索

赛场上没算明白不敢写

#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN =  3e5+7;
const ll mod = 1e9+7;
const ll inf = 0x3f3f3f3f;
int a[20][1050];
int f[MAXN];
int ans[MAXN];
int vis[MAXN];
int n,m;
void dfs(int p){
	int q=0;
	for(int i=1;i<=m;i++){
		if(f[a[p][i]]==0){
			q=a[p][i];
			break;
		}
	}
	f[q]=1;
	ans[q]=1;
	for(int i=1;i<=m;i++){
		if(vis[i]) continue;
		vis[i]=1;
		dfs(i);
		vis[i]=0;
	}
	f[q]=0;
	return;
}
void solve(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		for(int j=1;j<=n;j++) cin>>a[i][j];
	}
	for(int i=1;i<=m;i++){
		vis[i]=1;
		dfs(i);
		vis[i]=0;
	}
	int cnt=0;
	for(int i=1;i<=n;i++){
		if(ans[i]) cnt++;
	}
	cout<<cnt<<"\n";
	for(int i=1;i<=n;i++){
		if(ans[i])
		cout<<i<<" ";
	}
}

G. Remove the Prime

用n1/4分解质因数然后nim博弈 代码太长了不丢了

J. Increasing or Decreasing

先给它整体排序一遍 然后再从一遍开始一个一个对其 刚好n次


int n;
int a[N], p[N];
int pos[N];

struct ans
{
    int l, r;
    char ch;
} as[N];
int cnt = 0;

int cmp1(int &a, int &b)
{
    return a > b;
}

void solve()
{
    //	freopen("data.in.txt","r",stdin);
    //	freopen("data.out.txt","w",stdout);
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    as[++cnt] = {1, n, 'I'};
    sort(a + 1, a + 1 + n);
    for (int i = 1; i <= n; i++)
        pos[a[i]] = i;
    for (int i = 1; i <= n; i++)
        cin >> p[i];

    for (int i = n; i > 0; i--)
    {
        if (a[i] == p[i])
            continue;
        cnt++;
        int l = pos[p[i]], r = i;
        // cerr << l << ' ' << r << endl;
        sort(a + l, a + 1 + r);

        as[cnt].l = l;
        as[cnt].r = r;

        if (a[r] == p[i])
            as[cnt].ch = 'I';
        else
        {
            sort(a + l, a + 1 + r, cmp1);
            as[cnt].ch = 'D';
        }
        for (int j = l; j <= r; j++)
            pos[a[j]] = j;
        // for (int i = 1; i <= n; i++)
        //     cout << a[i] << ' ';
        // cout << endl;
    }
    cout << cnt << endl;
    for (int i = 1; i <= cnt; i++)
        cout << as[i].l << ' ' << as[i].r << ' ' << as[i].ch << endl;
}

M. Discrete Logarithm is a Joke

从最后一个数往前面跑 mod别写1e18+31 好像会爆ll

#include<bits/stdc++.h>
using namespace std;
#define int __int128
typedef long long ll;
const long long mod = 1000000000000000031;
int _power(int a,int b) {
	int ans=1,res=a;
	while(b) {
		if(b&1)
			ans=ans*res%mod;
			res=res*res%mod;
			b>>=1;
	}
	return ans%mod;
}
void cal() {
	long long n;
	cin>>n;
	long long st=300;
	for(int i=1000000-1; i>=n; i--) {
		st=_power(42,st);
	}
    cout<<st<<'\n';
}
posted @ 2023-08-17 02:08  xishuiw  阅读(86)  评论(1编辑  收藏  举报