总分:346/400
T1
分数:100
知识点:数学
思路:若区间长度 >= n,答案必为 n-1;否则将 L,R 对 n 取模,若 L <= R 则说明余数递增;否则说明区间跨过了 n 的倍数
Code
#include
using namespace std;
typedef long long ll;
typedef pair pii;
const int INF = 0x3f3f3f3f, maxn = 2e5+5;ll n,l,r,ans;
// l~r 取一数使得其模 n 最大int main()
{ios::sync_with_stdio(0);cin.tie(0);cin>>n>>l>>r;int length = r-l+1;if(length >= n) cout<
T2
分数:76
知识点:排序,思维
思路:不真排序,用 b[i] 维护每个元素的排名;修改时只调整 x 与其他元素相对顺序反转的部分
为什么没有想到正解思路:没利用“修改次数少”这一条件,把复杂度从询问转移到修改上
Code
#include // https://www.luogu.com.cn/article/8owdp7ef
using namespace std;
const int maxn = 8005; int n,q;
int a[maxn],b[maxn]; // b[i] = a[i] 的排名 void input()
{
cin>>n>>q;
for(int i=1;i<=n;i++)
{
cin>>a[i];
b[i] = 1;
}
} void init()
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
if(a[j] <= a[i]) b[i]++; // j 在 i 前面
else b[j]++; // j 在 i 后面
}
}
} int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
input();
init();
while(q--)
{
int op;
cin>>op;
if(op == 1)
{
int x,v;
cin>>x>>v;
int ax = a[x];
for(int i=1;i<=n;i++)
{
if(i == x) continue;
int num = a[i];
// 原来 i 是否在 x 前面
bool old_i_bef_x = (num < ax || (num == ax && i < x));
// 修改后 x 是否在 i 前面
bool new_x_bef_i = (num > v || (num == v && i > x));
// 原来 x 是否在 i 前面
bool old_x_bef_i = (num > ax || (num == ax && i > x));
// 修改后 i 是否在 x 前面
bool new_i_bef_x = (num < v || (num == v && i < x));
if(old_i_bef_x && new_x_bef_i) // 原来 i 在 x 前,现在 x 在 i 前 → x 排名上升
{
b[i]++; // i 被 x 超过,排名后移
b[x]--; // x 超过 i,排名前移
}
else if (old_x_bef_i && new_i_bef_x) // 原来 x 在 i 前,现在 i 在 x 前 → x 排名下降
{
b[i]--; // i 超过 x,排名前移
b[x]++; // x 被 i 超过,排名后移
}
// 其他情况相对顺序不变,排名不变
}
a[x] = v;
}
else
{
int x;
cin>>x;
cout<
T3
分数:100
知识点:模拟
思路:按题意模拟即可
Code
#include
using namespace std;
typedef long long ll;
typedef pair pii;
const int INF = 0x3f3f3f3f, maxn = 2e5+5;struct IP
{string s;string kind; // 服务端还是客户端ll a,b,c,d,e; //a.b.c.d:e bool f; //是否合规int idx,eid;vector dot;bool pre0(string s) {return ((int)s.size() > 1 && s[0] == '0');}int scnt(char c) {int cnt = 0;for(int i=0;i<(int)s.size();i++) if(s[i] == c) cnt++;return cnt;}int find(int l,char c) // 手写 find 更安心{for(int i=l;i<(int)s.size();i++) if(s[i] == c) return i;return -1;}string get(int l,char c) // 从 l 开始读入,遇到 c 停止{string res;for(int i=l;i<(int)s.size();i++) {if(s[i] == c) break;res += s[i];}return res;}bool num1(int x){return (x >= 0 && x <= 255);}bool num2(int x){return (x >= 0 && x <= 65535);}bool in() // 将数字读入a b c d e,同时判断是否合规{dot.clear();eid = -1;for(int i=0;i<(int)s.size();i++){if(s[i] == '.') dot.push_back(i);if(s[i] == ':') eid = i;}if(dot[2] > eid || dot[1] > eid || dot[0] > eid) return 0;string s = get(0,'.');if(pre0(s) || s.empty() || s.size() > 3) return 0;a = stol(s);if(!num1(a)) return 0;s = get(dot[0]+1,'.');if(pre0(s) || s.empty() || s.size() > 3) return 0;b = stol(s);if(!num1(b)) return 0;s = get(dot[1]+1,'.');if(pre0(s) || s.empty() || s.size() > 3) return 0;c = stol(s);if(!num1(c)) return 0;s = get(dot[2]+1,':');if(pre0(s) || s.empty() || s.size() > 3) return 0;d = stol(s);if(!num1(d)) return 0;s = get(eid+1,'#'); // # 是因为永远不会停止if(pre0(s) || s.empty() || s.size() > 5) return 0;e = stol(s);if(!num2(e)) return 0;return 1;}bool ok() // 是否合规{if(scnt('.') != 3) return 0;if(scnt(':') != 1) return 0;return in();}void input(int i) // 输入{cin>>kind>>s;idx = i;f = ok();}
};int main()
{ios::sync_with_stdio(0);cin.tie(0);int n;cin>>n;map connect;for(int i=1;i<=n;i++){IP ip;ip.input(i);if(!ip.f) {cout<<"ERR\n";continue;}if(ip.kind == "Server"){if(connect.count(ip.s)) cout<<"FAIL\n";else{connect[ip.s] = i;cout<<"OK\n";}}else{if(connect.count(ip.s)) cout<
T4
分数:70
知识点:链表,队列,set
思路:用两个 set 分别存苹果、桔子的位置,轮流取“大于上一位置的最小下标”,取不到就换行重来,每个元素只删一次。
为什么没有想到正解思路:没发现块是交替的,可以转化为“两种水果交替取下标”
Code
#include // https://www.luogu.com.cn/article/6f9lgett
using namespace std;
typedef long long ll;
typedef pair pii;int n;
set apple, orange;
int last = 0; // 当前果篮中上一个取走的位置
bool okapp; // 当前取苹果吗? void adjust()
{okapp = (*apple.begin() < *orange.begin());
}void outputLast(set &st)
{while(st.size() > 1){cout<<*st.begin()<<'\n'; // 取最左边一个,单独输出一行st.erase(st.begin());}
}int main()
{ios::sync_with_stdio(0);cin.tie(0);cin>>n;for(int i=1;i<=n;i++) {int x;cin>>x;if(x == 1) apple.insert(i);else orange.insert(i);}const int INF = n+1; // 哨兵apple.insert(INF);orange.insert(INF);adjust();while((okapp && apple.size() > 1) || (!okapp && orange.size() > 1)){if(okapp){int pos = *apple.upper_bound(last);if(pos == INF){// 苹果这边找不到了cout<<'\n';last = 0;adjust();}else{cout<