一、A
思路 : 这个我的数学垃圾,没有推出来那个式子,然后就是硬试出来的,这个n要么是4的整数倍,要么 mod 4 = 2 要么是6的整数倍,要mod 6 = 4 要么mod 6 = 2,其他情况都是不可能的 ,推式子的话我看别的博客里面有,这里就不推了
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define all(x) x.begin(),x.end()
#define PII pair<int,int>
#define ios ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
const int N = 20;
void solve()
{
int n; cin >> n;
if(n % 4 != 0 && n % 4 != 2 && n % 6 != 0 && n % 6 != 2 && n % 6 != 4) cout << "-1" << endl;
else if(n < 4) cout << "-1" << endl; //特判一下2
else
{
// 最多就先搞4个轮子的
int mi,mx;
mi = n / 6;
mx = n / 4;
if(n % 6 != 0)
mi++;
cout << mi << ' ' << mx << endl;
}
}
signed main()
{
ios;int T; cin >> T;
while(T -- ) solve();
return 0;
}
二、B
思路 题目是 单点修改,区间修改,区间查询,然后发现区间查询和区间修改只有一个区间就是1~n,当时一开始想的是树状数组,后来发现太复杂了,又看了一遍,发现可以用一个变量last存一下区间修改的数字,
当单点修改的时候,如果last变了,就用last,如果last没变或者已经使用过了,就用a[v]
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define all(x) x.begin(),x.end()
#define PII pair<int,int>
#define ios ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
const int N = 2e5 + 100,inf = -1e9 - 100;
int a[N];
int w[N];
void solve()
{
int n,q; cin >> n >> q;
for(int i = 1;i <= n;i ++ ) cin >> a[i];
int sum = 0,last = 0,cnt = 0;
for(int i = 1;i <= n;i ++ ) sum += a[i];
while(q -- )
{
int op,x,v; cin >> op;
if(op == 1)
{
cin >> v >> x;
if(w[v] != cnt)
sum += (x - last);
else
sum += (x - a[v]);
cout << sum << endl;
a[v] = x;
w[v] = cnt;
}
else
{
cin >> x;
sum = x * n;
last = x;
cnt++;
cout << sum << endl;
}
}
}
signed main()
{
ios;int T = 1;
while(T -- ) solve();
return 0;
}
三、C
思路,从题目可以知道我们如果想要的区间被全部摧毁,要么每一列都存在R,要么每一行都存在R,满足其中一个即可,所以可以用树状数组,开两个树状数组,一个存行,一个存列,
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define all(x) x.begin(),x.end()
#define PII pair<int,int>
#define ios ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
const int N = 1e5 + 100,inf = -1e9 - 100;
int trr[N],trc[N],column[N],row[N];
int n,q;
int lowbit(int x)
{
return x & -x;
}
void add(int x,int c,int st)
{
if(st)
for(int i = x;i <= n;i += lowbit(i))
trr[i] += c;
else
for(int i = x;i <= n;i += lowbit(i))
trc[i] += c;
}
int sum(int x,int st)
{
int ans = 0;
if(st)
for(int i = x;i >= 1;i -= lowbit(i))ans += trr[i];
else
for(int i = x;i >= 1;i -= lowbit(i))ans += trc[i];
return ans;
}
void solve()
{
cin >> n >> q;
while(q -- )
{
int op,x1,y1,x2,y2; cin >> op;
if(op == 1)
{
cin >> x1 >> y1;
if(row[x1] == 0)
{
add(x1,1,1);
}
if(column[y1] == 0)
{
add(y1,1,0);
}
row[x1]++;
column[y1]++;
}
else if(op == 2)
{
cin >> x1 >> y1;
row[x1]--;
column[y1]--;
if(row[x1] == 0)
{
add(x1,-1,1);
}
if(column[y1] == 0)
{
add(y1,-1,0);
}
}
else
{
cin >> x1 >> y1 >> x2 >> y2;
int r = x2 - x1 + 1;
int c = y2 - y1 + 1;
int r1 = sum(x2,1) - sum(x1 - 1,1);
int c1 = sum(y2,0) - sum(y1 - 1,0);
if(r == r1 || c == c1) cout << "Yes" << endl;
else cout << "No" << endl;
}
}
}
signed main()
{
ios;int T = 1;
while(T -- ) solve();
return 0;
}
四、D
思路 因为是要权值最大值最小,所以就是二分一下权值, mid就是此时枚举的最大的权值,然后重新建立一张图,比mid大的权值的点不要,因为是二分,规定了当前的最大权值是mid,然后拓扑序列来判断一下有没有回路,有的话最大权值取mid就一定可以,或者 当前的最长的路径的长度 >= k的话也可以,其他情况就不行
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define all(x) x.begin(),x.end()
#define PII pair<int,int>
#define ios ios::sync_with_stdio(false);cin.tie(0)
#define x first
#define y second
#define pb push_back
using namespace std;
const int N = 2e5 + 100,inf = -1e9 - 100;
vector<PII> e;
int w[N],d[N],dist[N];
int n,m,k;
vector<int> res[N];
bool check(int num)
{
queue<int> q;
for(int i = 0;i <= n;i ++ )
{
d[i] = 0; dist[i] = 0;
res[i].clear();
}
for(int i = 0;i < e.size();i ++ )
{
int u = e[i].x,v = e[i].y;
if(w[u] > num || w[v] > num) continue;
d[v]++;
res[u].pb(v);
}
for(int i = 1;i <= n;i ++ )
{
if(w[i] <= num && d[i] == 0)
{
q.push(i);
dist[i] = 1;
}
}
int mx = -1;
while(q.size())
{
int t = q.front(); q.pop();
mx = max(mx,dist[t]);
for(int i = 0;i < res[t].size();i ++ )
{
int j = res[t][i];
d[j]--;
if(d[j] == 0)
{
q.push(j);
dist[j] = dist[t] + 1;
}
}
}
if(mx >= k) return true;
else
{
for(int i = 1;i <= n;i ++ )
{
if(w[i] <= num && d[i] != 0)
{
return true;
}
}
return false;
}
}
void solve()
{
cin >> n >> m >> k;
for(int i = 1;i <= n;i ++ ) cin >> w[i];
while(m -- )
{
int u,v; cin >> u >> v;
e.pb({u,v});
}
//二分最大值
// 在子图中判断有没有环,有环一定是true 没有的话 就要判断最长的链的长度是不是 >= k
// 比mid权值大的都不能用
int l = 0,r = 1e9;
while(l <= r)
{
int mid = l + r >> 1;
if(check(mid))
{
r = mid - 1;
}
else
{
l = mid + 1;
}
}
if(l == 1e9 + 1)
cout << "-1" << endl;
else
cout << l << endl;
}
signed main()
{
ios;int T = 1;
while(T -- ) solve();
return 0;
}