总分: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<