一些特殊用法总结

pair<int,int> a[N];
sort(a+1,a+n+1);

可以对a[i].first进行排序 即对第一个元素进行排序
踩到坑了 还有一种情况
在这里插入图片描述

bool cmp(pii a,pii b)//对second元素做要求
{
    if(a.first==b.first) return a.second<b.second;
    else return a.first<b.first;
}
#include<iostream>
#include<algorithm>

using namespace std;
typedef pair<int,int> pii;
pii a[10];

bool cmp(pii a,pii b)
{
    if(a.first==b.first) return a.second<b.second;
    else return a.first<b.first;
}

int main()
{
    int n=0,i,j;
    while(~scanf("%d%d",&i,&j))
    {
        n++;
        if(i<=j) a[n].first=i,a[n].second=j;
        else a[n].first=j,a[n].second=i;
        if(n==6)
        {
            n=0;
            //sort(a+1,a+7,cmp);
            sort(a+1,a+7);
            int k=0;
            
            //判断是不是三对边
            for(int i=1;i<=6;i+=2)
            {
                if(a[i].first==a[i+1].first&&a[i].second==a[i+1].second) k++;
                else break;
            }
            
            //for(int i=1;i<=6;i++) printf("%d %d\n",a[i].first,a[i].second);
            
            if(k!=3) 
            {
                puts("IMPOSSIBLE");
                continue;
            }
            
            //for(int i=1;i<=6;i++) printf("%d %d\n",a[i].first,a[i].second);
            
            int res1,res2;//判断正方体
            if(a[1].first==a[1].second)
            {
                k=0;
                res1=a[1].first,res2=a[1].second;
                for(int i=1;i<=6;i+=2)
                {
                    if(a[i].first==res1&&a[i].second==res2) k++;
                }
                if(k==3) 
                {
                    puts("POSSIBLE");
                    continue;
                }
            }
            
            bool st=0;//判断长方体
            if(a[1].first==a[3].first)
            {
                res1=a[1].second,res2=a[3].second;
                if((a[5].first==res1&&a[5].second==res2)||(a[5].first==res2&&a[5].second==res1)) st=1;
                else st=0;
            }
            
            
            if(st) puts("POSSIBLE");
            else puts("IMPOSSIBLE");
        }
    }
    
    return 0;
}

/*
2 3
2 4
2 5 
2 3
3 4
3 5

1 2
1 3
1 4 
1 1
1 6
1 5

5 2
4 3
3 4 
1 1
3 6
6 5
*/

2在这里插入图片描述*min_element(a,a+n) *max_element(a,a+n) 求数组的最小最大值
3.

for(int i=1;i<=n;i++)
        {
            ans[++cnt]=num;
            int count=0;
            for(int j=i;j<=n;j++)
            {
                f[a[j]]--;
                //printf("j=%d f[%d]=%d\n",j,a[j],f[a[j]]);
                if(f[a[j]]==0) num=min(a[j],num);
                if(a[j]<ans[cnt]&&!st[a[j]]) count++,st[a[j]]=1;
                if(count==ans[cnt])
                {
                    //memset(st,0,sizeof st);  速度比下面慢
                    for(int k=0;k<ans[cnt];k++) st[k]=0;
                    i=j;//进入上面循环  i会自动加一
                    break;
                }
            }
        }

for循环进入会自动加一 memset速度比遍历慢
4.erase用法在这里插入图片描述5.
lower_bound( )和upper_bound( )都是利用二分查找的方法在一个排好序的数组中进行查找的。

在从小到大的排序数组中,

lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

int find(int x)
{
    return lower_bound(s,s+j,x)-s;
}

二分查找

6.struct 用法 及排序问题

bool cmp1(str a,str b)//不用加中括号
#include<iostream>
#include<algorithm>

using namespace std;
const int N=2e5+10;
struct str{
    int x,w,pos;
} a[N],b[N];
int t,m,n;

bool cmp1(str a,str b)
{
    return a.w<b.w;
}

bool cmp2(str a,str b)
{
    return a.x<b.x;
}


int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&a[i].x,&a[i].w);
            a[i].pos=i;
        }
        
        sort(a+1,a+m+1,cmp1);
        
        long long ans=0;
        for(int i=1;i<=2*n;i++)
        {
            ans+=a[i].w;
            b[i].x=a[i].x;
            b[i].w=a[i].w;
            b[i].pos=a[i].pos;
        }
        
        sort(b+1,b+2*n+1,cmp2);
        
        printf("%lld\n",ans);
        
        for(int i=1;i<=n;i++)
        {
            printf("%d %d\n",b[i].pos,b[2*n+1-i].pos);
        }
        puts("");
    }
    
    return 0;
}
<think>嗯,用户这次想了解编程语言中赋值号的特殊用法。从用户提供的历史引用来看,站内引用[1]和[2]分别介绍了Java和C语言中的特殊符号,而引用[3]则提到了Shell脚本中赋值时处理特殊字符的注意事项。不过用户明确表示这些引用只是参考,真正需求是基于赋值号的特殊用法。用户之前的问题是关于数学符号在编程中的写法,现在转向赋值操作符的特殊用法,说明ta可能在学习编程基础或准备处理特定场景的赋值问题。考虑到赋值号虽然看似简单,但在不同语言中有很多值得注意的特殊用法。准备从六个方面展开:链式赋值可以让多个变量同时获得相同值,比如Python里的a=b=0;多重赋值能优雅地交换变量或同时初始化多个值,Python中x,y=y,x就是经典应用;复合赋值运算符如+=能简化运算,但要注意前缀/后缀递增的副作用;特殊类型赋值中,指针赋值需要特别注意深/浅拷贝问题;条件赋值特性如三元运算符能让代码更简洁;原始字符串赋值在遇到特殊字符时需要不同的处理方式,比如Shell中单引号和双引号的区别。这些用法覆盖了主流通用语言的核心特性,但具体实现会有差异。用户在Shell脚本方面可能需要特别提醒单引号的原始字符串特性(如引用[3]提到的防转义),在C/C++中则要强调指针赋值的风险控制。最后用两段话总结要点,帮助用户建立记忆锚点:既要认识到语法糖的便利性,也要警惕不同语言的陷阱区域。相关问题设计着重延伸赋值操作符的知识边界:从替代方案(自定义逻辑或特定范式)到语言差异性(函数式语言的不可变性),再到最佳实践(代码可读性平衡),最后回溯到赋值本质(堆栈内存层面)。这些问题既能帮助用户深化理解,也可能暗示ta后续可能遇到的进阶问题。</think> 好的,理解您的问题。赋值号 (`=`) 在编程语言中最基本的用途是将右侧的值存储到左侧的变量中。然而,在不同语言和特定场景下,它有一些**特殊用法或与之相关的注意事项**,以下是一些关键点: 1. **链式赋值 (Chained Assignment):** * **用法:** 允许将同一个值同时赋值给多个变量。一条语句内连续使用多个赋值运算符。 * **示例:** ```python # Python a = b = c = 10 # a, b, c 都被赋值为 10 ``` ```javascript // JavaScript let x, y, z; x = y = z = 20; // x, y, z 都被赋值为 20 ``` * **注意:** 执行顺序通常是**从右向左**。先计算最右侧的值(`c = 10` 或 `z = 20`),然后将这个值依次赋给左侧的变量(`b = c` 或 `y = z`, `a = b` 或 `x = y`)。在涉及对象引用或复杂表达式时需谨慎计算顺序。 2. **多重赋值/解构赋值 (Multiple/Destructuring Assignment):** * **用法:** 将多个值(通常是来自数组、元组或对象)一次性分别赋值给多个变量。 * **示例:** ```python # Python (元组解包/迭代解包) a, b = (1, 2) # a = 1, b = 2 a, b = b, a # 交换变量值:a 和 b 的值互换 c, d, *e = [1, 2, 3, 4, 5] # c=1, d=2, e=[3,4,5] (带剩余元素的解包) ``` ```javascript // JavaScript (数组/对象解构) const [first, second] = [10, 20]; // first = 10, second = 20 const {name, age} = {name: 'Alice', age: 30}; // name = 'Alice', age = 30 ``` ```go // Go (多返回值赋值) result, err := someFunction() // 函数返回两个值,分别赋给 result 和 err ``` * **优势:** 代码简洁,特别是用于交换变量、函数返回多个值、提取数据结构内容时非常方便。赋值号在这里扮演着将右边结构化数据进行“拆解”并分配到左边变量的角色。 3. **复合赋值运算符 (Compound Assignment Operators):** * **用法:** 将某个运算和赋值操作合并为一个操作符。这些运算符可以被看作是 `=` 的增强版本。 * **示例(几乎所有主流语言都支持类似形式):** * `+=`: `a += 5;` 等价于 `a = a + 5;` * `-=`: `b -= 3;` 等价于 `b = b - 3;` * `*=`, `/=`, `%=`, `<<=`, `>>=`, `&=`, `|=`, `^=` 等操作类似。 * 特殊地,在 C/C++/C#/Java 等语言中,递增/递减运算符 `++` 和 `--` (`a++`, `++a`, `a--`, `--a`) 也包含了赋值操作,但它们本质上是独立运算符而非赋值运算符的变体。需要特别注意它们的副作用(值变化发生在表达式求值之前还是之后)[^3]。 * **优势:** 更简洁,尤其对于修改变量自身值的情况。 4. **对特殊类型(特别是引用类型)赋值的影响:** * **用法:** 对引用类型(如对象、数组、切片、映射、指针)进行赋值操作时,通常复制的是**引用(地址)** 而非实际数据本身。这一点是赋值操作的核心,但也容易被误解为复制数据。 * **示例:** ```javascript // JavaScript let obj1 = { value: 100 }; let obj2 = obj1; // obj2 现在引用了和 obj1 同一个对象 obj2.value = 200; console.log(obj1.value); // 输出 200! 因为修改的是同一个对象 ``` ```go // Go slice1 := []int{1, 2, 3} slice2 := slice1 // slice2 和 slice1 共享底层数组 slice2[0] = 9 fmt.Println(slice1) // 输出 [9 2 3] ``` * **注意:** 要创建数据的**真正副本(深拷贝)**,通常需要语言特定的方法(如 JavaScript 的 `JSON.parse(JSON.stringify())` 或扩展运算符 `...` 对数组/对象的浅拷贝(对于对象属性也是引用拷贝),Go 的 `copy` (用于切片) 或显式遍历赋值),仅仅使用 `=` 是无法实现的(只做引用拷贝/浅拷贝)[^3]。 5. **条件赋值 / 三元运算符中的赋值:** * **用法:** 可以将赋值操作嵌入到条件表达式中。虽然不是赋值号本身的特殊写法,但展现了与其他运算符的结合使用。 * **示例:** ```javascript // JavaScript (三元运算符) const max = (a > b) ? a : b; // 将 a 和 b 中较大的值赋给 max ``` ```python # Python (三元条件表达式) status = 'active' if is_user_active else 'inactive' # 根据条件赋不同的值 ``` 6. **赋值与转义字符/原始字符串:** * 当字符串中包含特殊字符(如引号 `"`, `'`,路径分隔符 `\`,变量符号 `$`)时,赋值给字符串变量需要处理: * **用法:** 需使用反斜杠 `\` 转义,或者使用原始字符串字面量(其含义是字面值),通常由前缀定义(如 Python 的 `r''`,C# 的 `@""`,JavaScript 的 String.raw 模板字面量 `String.raw` )。 * **示例:** ```python # Python path = r'C:\Users\Documents' # 原始字符串,\U 等不会被解释为特殊字符 message = "He said, \"Hello!\"" # 用转义符 \" 表示双引号本身 ``` ```bash # Shell Script (参考引用3) var='This contains a $ sign and a ` backtick and a "double quote" literally.' # 单引号内内容原样输出 var="Price: \$100" # 双引号内需要对 $ 转义才能输出 $ 本身 ``` ```javascript // JavaScript const command = `echo "Hello $USER"`; // 模板字面量中的 $USER 会被解释为变量 const literalDollar = `Price: \$${100}`; // 使用 \ 转义 $ 才能输出 $ ``` **总结关键点:** 1. **`=` 是赋值,非相等判断:** 最基础的,也是常见错误,比较通常用 `==` 或 `===`。 2. **链式赋值简化代码:** 但要注意计算顺序(右到左)。 3. **解构赋值提升效率:** 尤其适合处理函数多返回值或数据结构。 4. **复合运算符高效简洁:** 用于变量自身更新。 5. **引用类型赋值传地址:** `objectA = objectB` 让两者指向同一数据,修改其一影响另一。深拷贝需额外操作。 6. **原始字符串和转义字符:** 赋值包含特殊字符的字面量时,务必正确使用原始字符串前缀或转义符 `\` 来避免解释错误。在 Shell 中尤其要注意单引号 `''` 和双引号 `""` 对变量扩展和转义的不同规则 [^3]。 7. **条件赋值场景:** 结合三元运算符等实现更灵活的赋值逻辑。 理解这些特殊用法和注意事项,对于编写正确、高效和易维护的代码至关重要,特别是在处理引用、字符串和需要特殊赋值的复杂逻辑时。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值